In our previous post, Unit Testing in C#, Calculator class under test does not have any dependencies. We need not create any other class instance other than Calculator’s. But this is not usually the case in production environment. Here we will see unit testing approach for the classes having one or more dependencies.
Before we start to explain mocking, remember that one of the concepts of Unit testing is isolation of class under test; this means that dependencies of the class under test should have minimum or no affect on test outcome. This becomes possible when we can mimic the dependencies in the test class with objects which we can control and dictate.
‘Mock’ is something which is not real, is an imitation of a real object. So, Mocking in Unit tests is creating replica objects of real dependencies of class under test, which we can control in test environment.
Let’s start by how we create these mock objects. We can implement mock objects by ourselves or better we should take help of mocking frameworks available such as NMock, Moq for C#, Gmock for C++, Mockito, JMock, EasyMock for Java.
Here for the demonstration, I have a Logger class which has two dependencies, IWriter and IDateTimeProvider, responsibilities for each is evident from the names of interfaces. Logger methods for e.g., LogInfo calls Write method of IWriter‘s implementation. Thus we need to verify in our unit tests whether call to the Write method is done with desired argument or not.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Now, in unit test class for creating Logger instance, we need not to create instance of its dependencies, instead we can create mock objects.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
In above LoggerTest class, we have used Moq framework, which gives powerful APIs such as Setup and Verify; using Setup, we can arrange desired return value from the mocked object’s properties and methods; using Verify, we can assert whether the call to the mocked object’s method is created or not.
For creating mock objects, Moq gives Mock<T> type where T is the type for which mock object is to be created. Usually for creating mock objects, dependencies of the class are preferred to be of interface types which both results in better abstraction and loose coupling.
Moq library can be download as nuget package from nuget website. Extract the package with WinZip or 7Zip and refer Moq.dll as assembly reference in your unit test project.