Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The HighestNumberFinder is designed to return an integer representing the number in a group of numbers. This can easily be stubbed out.Here is the Stub

Begin by creating a new test

Code Block
languagec#
namespace TopicManagerService
{[Test]
      public class HighestNumberFinderpublic void find_heighest_score_with_array_of_one_return_array_of_one_using_stub()
  {      {
  public int findHighestNumber(int[] values)       // Arrange
{             return 89;int[] scores = { 56, 67, 45, 89 };
            string topicName = "Physics";
            }TopicScores[] topicScores = { new TopicScores(topicName, scores) }
}

But when you try and use this class in the tests, you should see type errors. This is because, in the implementation unit of TopicManager, it's typed against HighestNumberFinder in a namespace called FindHighestNumberService.v6. So namespaces do not offer us the solution we are looking for.

Here are the modified tests

Code Block
languagec#
using NUnit.Framework;

namespace TopicManagerService
{;
            publicIHighestNumberFinder hnf class= TopicManagerTests
new TopicManagerServiceStubs.HighestNumberFinder();
   {         [Test]TopicManager cut = new TopicManager(hnf);
    public void find_heighest_score_in_empty_array_return_empty_array()      TopicTopScore[] expectedResult = { new TopicTopScore(topicName, 89) };

       // Arrange    // Act
       TopicScores[] topicScores = Array.Empty<TopicScores>();     TopicTopScore[]        HighestNumberFinder hnf = new HighestNumberFinder(result = cut.findTopicHighScores(topicScores);

           TopicManager cut = new TopicManager(hnf);// Assert
             TopicTopScore[] expectedResult = Array.Empty<TopicTopScore>(Assert.AreEqual(result[0].TopicName, expectedResult[0].TopicName);
             // ActAssert.AreEqual(result[0].TopScore, expectedResult[0].TopScore);
        }
    TopicTopScore[] result = cut.findTopicHighScores(topicScores);}

Here is the Stub. We have put it in a different namespace in the test project

Code Block
languagec#
namespace TopicManagerServiceStubs
{
    public class HighestNumberFinder
    {
  // Assert     public        Assert.That(result, Is.EqualTo(expectedResult));int findHighestNumber(int[] values)
        }

      {
 [Test]         public void find_heighest_score_with_array_of_one_return_array_of_one()
 89;
       { }
           // Arrange
            int[] scores = { 56, 67, 45, 89 };
            string topicName = "Physics";
            TopicScores[] topicScores = { new TopicScores(topicName, scores) };
    }
}

But when you try and use this class in the tests, you should see type errors in all the tests. This is because, in the implementation unit of TopicManager, it's typed against HighestNumberFinder in a namespace called FindHighestNumberService.v6. So namespaces do not offer us the solution we are looking for.

Here are the updated tests. Alternatively, you could modify TopicManager so it has a default constructor, but you will need to think about different issues and more tests for if TopicManager default constructor is used.

Code Block
languagec#
using NUnit.Framework;

namespace TopicManagerService
{
    public class TopicManagerTests
    {
       HighestNumberFinder hnf[Test]
= new HighestNumberFinder();      public void find_heighest_score_in_empty_array_return_empty_array()
    TopicManager cut = new TopicManager(hnf);{
            TopicTopScore[] expectedResult = {new TopicTopScore(topicName, 89)};// Arrange
            TopicScores[] topicScores = Array.Empty<TopicScores>();
 // Act          HighestNumberFinder hnf = TopicTopScore[] result = cut.findTopicHighScores(topicScoresnew HighestNumberFinder();
             // AssertTopicManager cut = new TopicManager(hnf);
            Assert.AreEqual(resultTopicTopScore[0].TopicName, expectedResult[0].TopicName = Array.Empty<TopicTopScore>();

           Assert.AreEqual(result[0].TopScore, expectedResult[0].TopScore);
 // Act
       }     }
}

Observe errors on lines 14 and 32.

We need to use interfaces. And the interface needs to be in a place that is available to both production code and tests.

...

Create a new interface that is part of the HighestNumberFinder project

...

languagec#

...

TopicTopScore[] result = cut.findTopicHighScores(topicScores);

            // Assert
            Assert.That(result, Is.EqualTo(expectedResult));
      

...

 

...

 

...

}

   

...

     [Test]
   

...

 

...

 

...

   public 

...

Copy HighestNumberFinder.v6 to HighestNumberFinderFinal and refactor the class so that it implements the interface above

...

languagec#

...

void find_heighest_score_with_array_of_one_return_array_of_one()
        {
    

...

 

...

 

...

 

...

 

...

    // 

...

Arrange
          

...

 

...

 int[] scores = { 56, 67, 45, 89 };
         

...

   string topicName 

...

= "Physics";
   

...

 

...

 

...

 

...

 

...

     

...

TopicScores[] topicScores = { new TopicScores(topicName, scores) };
 

...

 

...

 

...

 

...

        HighestNumberFinder 

...

hnf = new HighestNumberFinder();
         

...

 

...

 

...

 

...

TopicManager cut = new TopicManager(hnf);
            

...

TopicTopScore[] expectedResult = {new 

...

TopicTopScore(

...

topicName, 89)};

            

...

// 

...

Act

...

 

...

           TopicTopScore[] result 

...

= cut.findTopicHighScores(topicScores);

            // Assert
     

...

       

...

Assert.AreEqual(result[0].TopicName, expectedResult[0].TopicName);
            Assert.AreEqual(result[0].TopScore, expectedResult[0].TopScore);
      

...

 

...

 

...

}
    }
}

To give us more flexibility, we need to use an interface. And the interface needs to be in a place that is available to both production code and tests.

  1. Create a new interface that is part of the HighestNumberFinder production project

  2. Code Block
    languagec#
    namespace FindHighestNumberService
    {
        }public interface IHighestNumberFinder
         {
        return result;   int      }findHighestNumber(int[] values);
        }
    }
  3. Copy HighestNumberFinder.v6 to HighestNumberFinderFinal

  4. Refactor the tests class so that the HighestNumberFinder is instantiated as followsit implements the interface above

  5. Code Block
    languagec#
    using System;
    using FindHighestNumberService;
    
    namespace FindHighestNumberServiceFinal
    {
     IHighestNumberFinder hnf = new FindHighestNumberServiceFinal.HighestNumberFinder();
  6. Refactor TopicManager so it now works with the interface IHighestNumberFinder and not directly with the implementation class

  7. Rerun all your tests they should still be passing.

Tip

The tests have given us the confidence to refactor the code and begin to think more clearly about our implementation.

Now let’s substitute a stub in place of the real implementation of HighestNumberFinder.

  1. Create a new called find_heighest_score_with_array_of_one_return_array_of_one_using_stub(), it's a copy of find_heighest_score_with_array_of_one_return_array_of_one()

  2. Code Block
    languagec#
            [Test]   public class EmptyArrayException : Exception
        {
            public EmptyArrayException(string message):base(message)
            {
            }
        }
        public class HighestNumberFinder : IHighestNumberFinder
        {
            public int findHighestNumber(int[] values)
            {
                public void find_heighest_score_with_array_of_one_return_array_of_one_using_stub()if (values.Length < 1)
                 {   throw new EmptyArrayException("Array is empty");
    
                int result = Int32.MinValue;
    //
    Arrange            for (int[] scoresi = 0; {i 56, 67, 45, 89 };< values.Length; i++)
                {
     string topicName = "Physics";            if TopicScores(values[i] topicScores = { new TopicScores(topicName, scores) };
    > result)
               IHighestNumberFinder hnf = new FindHighestNumberServiceFinal.HighestNumberFinder();     result = values[i];
         TopicManager cut = new TopicManager(hnf);   }
             TopicTopScore[] expectedResult = { new TopicTopScore(topicName, 89) } return result;
            }
        // Act
     }
    }
  3. Modify the Stub version so it also implements IHighestNumberFinder

  4. Refactor TopicManager so it now works with the interface IHighestNumberFinder and not directly with the implementation class

  5. Code Block
    languagec#
    namespace TopicManagerServiceStubs
    {
        public class TopicManager
       TopicTopScore[] result{
    = cut.findTopicHighScores(topicScores);       private IHighestNumberFinder highestNumberFinder;
    
       // Assert    public  TopicManager( IHighestNumberFinder hnf )
       Assert.AreEqual(result[0].TopicName, expectedResult[0].TopicName);    {
            Assert.AreEqual(result[0].TopScore, expectedResult[0].TopScore);   highestNumberFinder = hnf;
       }     }
  6. Modify line 8 to

  7. Code Block
    languagec#
    
        IHighestNumberFinder hnf = new TopicManagerService.HighestNumberFinder();
    The error is because of TopicManagerTests
    .
    HighestNumberFinder does not implement the IHighestNumberFinder interface
    .
    Modify it so that it does.
  8. Rerun the all your tests , they should all passthey should still be passing.

Tip

The tests have given us the confidence to refactor the code and begin to think more clearly about our implementation.

Info

We’ve now created a controlled environment for our tests

...

One of the results will fail. Why?

Sample Solution

QLC-2.4 Mocks, complete the last TopicManager requirement

•If the input is [{“Physics”, {56, 67, 45, 89}}, {“Art”, {87, 66, 78}}, {“Comp Sci”, {45, 88, 97, 56}}], the result should be [{“Physics”, 89}, {“Art”, 87}, {“Comp Sci”, 97}]

Sample Solution