...
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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
...
language | c# |
---|
...
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
...
language | c# |
---|
...
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.
Create a new interface that is part of the
HighestNumberFinder
production projectCode Block language c# namespace FindHighestNumberService { }public interface IHighestNumberFinder { return result; int }findHighestNumber(int[] values); } }
Copy HighestNumberFinder.v6 to
HighestNumberFinderFinal
Refactor the tests class so that the
HighestNumberFinder
is instantiated as followsit implements the interface aboveCode Block language c# using System; using FindHighestNumberService; namespace FindHighestNumberServiceFinal { IHighestNumberFinder hnf = new FindHighestNumberServiceFinal.HighestNumberFinder();
Refactor
TopicManager
so it now works with the interfaceIHighestNumberFinder
and not directly with the implementation classRerun 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
.
Create a new called
find_heighest_score_with_array_of_one_return_array_of_one_using_stub()
, it's a copy offind_heighest_score_with_array_of_one_return_array_of_one()
Code Block language c# [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 } }
Modify the Stub version so it also implements
IHighestNumberFinder
Refactor
TopicManager
so it now works with the interfaceIHighestNumberFinder
and not directly with the implementation classCode Block language c# 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; } }
Modify line 8 to
The error is because of TopicManagerTestsCode Block language c# IHighestNumberFinder hnf = new TopicManagerService.HighestNumberFinder();
HighestNumberFinder does not implement the.
IHighestNumberFinder
interface
Modify it so that it does..
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?
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}]