Mocking
While writing unit tests, the class under test may have dependencies. And these dependencies may be impossible to instantiate in a test fixture or they may be very difficult to setup. To make unit testing simpler and to focus on the code being tested, not on the behavior or state of external dependencies, software developers use the technique called mocking.
In mocking, the dependencies are replaced by artificial objects that simulate the behavior of the real ones. Mock objects have the same interface as the real objects they mimic, allowing a client object to remain unaware of whether it is using a real object or a mock object.
NOTE: Frequently, the words mock and substitute are used interchangeably.
Setting Up the NSubstitute Framework
For every programming language, there exists a mocking framework that makes it easy to mock real objects. NSubstitute is not the only package for C#, but it is a common one.
- Use the Nuget Package Manager to browse for NSubstitute and add it to your test project.
- In your test project, add a using statement for NSubstitute.
Now your repository can be assigned to a substitute for the IRepository.
Using NSubstitute in Tests
For example, we can now create tests in our Courses project for the CourseController, which depends upon a CourseRepository.
In CourseControllerTests, let's declare the controller and repository objects we will use in our tests:
CourseController underTest;
IRepository<Course> courseRepo;
Then in the constructor of our CourseControllerTests() we can use NSubstitute to create a Substitute for the Courses repository:
courseRepo = Substitute.For<IRepository<Course>>();
And also in the constructor, this substitute for the Courses repository can be injected into the Courses Controller:
underTest = new CourseController(courseRepo);
Our CourseController will now interact with a substitute for our Course repository, instead of the actual data in our underlying database.
Now when we call a method of the Course repository, we use NSubstitute's Return() method to return an expected value for the action:
var expectedCourses = new List<Course>();
courseRepo.GetAll().Returns(expectedCourses)
Here is an example of NSubstitute in action in the CourseControllerTests class:
public class CourseControllerTests
{
CourseController underTest;
IRepository<Course> courseRepo;
public CourseControllerTests()
{
courseRepo = Substitute.For<IRepository<Course>>();
underTest = new CourseController(courseRepo);
}
[Fact]
public void Index_Returns_A_View()
{
var result = underTest.Index();
Assert.IsType<ViewResult>(result);
}
[Fact]
public void Index_Passes_All_Courses_To_View()
{
var expectedCourses = new List<Course>();
courseRepo.GetAll().Returns(expectedCourses);
var result = underTest.Index();
Assert.Equal(expectedCourses, result.Model);
}
[Fact]
public void Details_Returns_A_View()
{
var result = underTest.Details(1);
Assert.IsType<ViewResult>(result);
}
[Fact]
public void Details_Passes_Course_To_View()
{
var expectedCourse = new Course();
courseRepo.GetById(1).Returns(expectedCourse);
var result = underTest.Details(1);
Assert.Equal(expectedCourse, result.Model);
}
}