So let’s just dive in today. Our current test class is fairly clean and straightforward, but we’re not using all of Moq’s capabilities yet. One notable thing is that we have to remember to call VerifyAll on all of our individual mocks. Fortunately, Moq provides us with a tool to mitigate this problem: MockRepository is a class we can use to create and track mocks, and verify all expectations at once.
So how does MockRepository work?
Here’s our familiar test class, but updated to use MockRepository. The fun begins on line 6 where we declare and create a MockRepository instance. The next changes are in our SetUp method – note how we’re using mockRepository.Create<T> instead of new Mock<T>. The end result is the same so what exactly does this get us?
As mentioned before, the repository acts as a container for all of the mocks we create. Notice also that we configure it, providing a MockBehavior to use for all created mocks. When we create a mock using this pattern, the repository takes an additional step, adding it to its internal registry of ‘known’ mock instances.
We see the other value of this approach on lines 38 and 48: Note that in both cases there is a single call to MockRepository.VerifyAll() – literally that’s all we need to do.
So we’ve streamlined our test pretty nicely, but there’s still another improvement we can make.
Improving the Code With a Base Class:
In a nutshell, we can see that as our test suite (group of test fixtures) grows, there will be more and more duplicated boilerplate code, for example creating the MockRepository. Each test suite will also follow a very similar pattern during Setup. Finally, we want our test fixtures to focus as much as possible on the actual tests – we don’t want to always have to worry about the ins and outs of Moq.
Let’s create a base class that can be used by all of our tests:
This class can act as a base class for any type, gives us some nice extensibility points (the abstract methods), and hides most of the Moq-specific details. Let’s take a look at some highlights:
Starting at line 5, we see that the TestBase class is generic, which lets us specify which type this class is working with. We use type T both in CreateSystemUnderTest and the SystemUnderTest property. It’s also worth noting that this test class isn’t intended to be instantiated directly, so it is marked as abstract.
Next, we have a SetUp method like we did in our original class, but it’s a little bit more abstracted, illustrating the steps in configuring a test. Take note that the ConfigureConstructorMocks, CreateMocks, and CreateSystemUnderTest methods are all specified as abstract. This means that classes deriving from TestBase must implement those methods. If that sounds confusing, don’t worry – I’ll have an example coming up in a few moments.
Then there are the CreateMock<TMock> and VerifyAllMocks methods – these are what implementing classes will call instead of calling MockRepository directly.
Finally, notice that we moved the Constructor_Always_PerformsRequiredWork test into the base class. That way we don’t have to implement it in every test fixture.
So now that we have this in place, let’s update the ReallyHardToTest class:
Probably the biggest differences here are:
- Although we still have a SetUp method, we’re only creating a non-mocked instance in it. The method is also marked as override, so it overrides the base SetUp method. We still want the base class logic to execute though, so at the end of our SetUp method, we call base.SetUp() to complete the chain.
- The three abstract methods from the base class (CreateMocks, ConfigureConstructorMocks, and CreateSystemUnderTest) are all implemented here. Each method clearly describes the work to be done (e.g. “Create our mocks”), giving a clear flow to the test fixture.
- We now verify mocks using the VerifyAllMocks() method instead of MockRepository directly
- Our test class derives from TestBase<T>, which provides us with reusable base functionality
In the end, our test fixture is very clean, extremely focused on the unit-specific tests, and easy to understand. I can explain it to the monkey in about a minute, less if the monkey already knows about TestBase. Another advantage of extracting the base test class is that tests using it will all follow the same pattern, enhancing code consistency.
So it’s been quite a journey!
- We learned about common testability issues, starting with a simple class that was written in such a way as to be untestable.
- Gradually, we refactored the class, introducing various strategies to eliminate testing challenges:
- Dependency Injection allows us to control dependencies at test time
- Wrapper classes to eliminate static dependencies
- Programming to the Abstraction to reduce coupling and enable runtime/test time substitution of dependency implementations
- Factories to resolve runtime dependencies and avoid the new keyword
- Along the way we took a dip into some more advanced Moq features, including MockRepository, that help to simplify working with mocks (this tutorial)
- At the end, we extracted common functionality into a reusable base test class, letting us focus on writing tests instead of infrastructure
We’ve come a long way in just a few tutorials, but there’s still more to learn. Stay tuned for more Unit Testing goodness!