Applications usually consists of many classes which interacts with each other to achieve the desired functionality , this is how object oriented applications are structured.This object oriented approach for developing applications could be a problem while unit testing the different classes and methods.
Unit testing means testing the smallest unit of code such as method or class in isolation to other methods and classes in the application.But if we have a method which creates an object of some other class or calls another method then this could make the method difficult to unit test.If we test a method which depends upon other classes or methods then we are doing integration testing and not unit testing.
Suppose our method access some database using data access layer then we will need to make the database call to unit test our method.As our method already contains the database access logic so while unit testing such a method we have no choice but to let the method access the database.
Though we can comment the database access logic in our method,this is not an ideal solution as the unit test will test the modified code and not the original code.
One solution is to write a mock class which can be used instead of the original database access class and this mock class will not hit the actual database.We can implement this by programming to interface in our method.
So if our method is using the database access layer class then instead of directly creating an object of this class we can pass the dependency using an interface to the method.The advantage of this approach is that we can easily pass another database access class ,or even our mock class,instead of always passing the same class.
Mock object simulate or mimic a real object.It has the same interface as the real object so the client can use the mock object in the same manner it uses the real object.Our method is the client here.
There are few frameworks for creating mock objects.Moq is a popular open source framework for .NET for creating mock objects.We will see some of the common options for creating mock objects using the Moq framework.
To use the Moq mocking framework in our application we need to follow the below steps:
1. Add a reference to the Moq
To use the Moq library in the project we need to install Nuget package for Moq.
This will add the required references for the Moq framework to the project.
2.Import the Moq namespace
3.Create Mock object
We need to tell Moq what type of object we want to mock.We do this passing the type parameter to the Mock generic type as:
Mock<TypeToMock> mockType=new Mock<TypeToMock>();
above line tells the Moq library that we are mocking the “TypeToMock” type.
So we create a mock object for a specific type.
4.Setting the expectation or behaviour
Moq uses lambda expressions,generics and delegates which makes Moq suitable for .NET applications.To define the behaviour we use the Setup method as:
mockType.Setup(x=>x.MethodName(It.IsAny<int>())).Returns(()=>null);
The above line demonstrates some of the important concepts used in the Moq mocking framework.The three main methods used above are
- Setup() Used for defining the behaviour of a method.The above code is setting the behaviour of the MethodName method.
- It.IsAny() “It” is a static class containing various methods used to set the parameter expectations.It.IsAny<int>() means the method will accept any parameter of integer type.
- Returns() This method is used for returning values from the method passed in the Setup() method.The above Returns() method will return a null when the “MethodName” method is called with an integer value.
The Setup method is passed a parameter of the type of “mockType” ,so we can access the methods and properties of the mockType in the Setup method.In the above code we are defining the mocking behavior for the MethodName() method.Returns() method defines the result which the MethodName() method will return.
Simple Moq example:
In the following example we have defined an Employee class.The method GetDateofJoining(int id) is not implemented by the Employee class.So if we want to test the Employee class then we need create the mock object of the Employee class.We are mocking the GetDateofJoining(int id) method below ,it returns the current date as the date of joining.
public class Employee { public virtual DateTime GetDateofJoining(int id) { throw new NotImplementedException(); } } class Program { static void Main(string[] args) { var employee=new Mock<Employee>(); employee.Setup(x => x.GetDateofJoining(It.IsAny<int>())).Returns((int x) => DateTime.Now); Console.WriteLine(employee.Object.GetDateofJoining(1)); Console.ReadLine(); } }
On running the above code we get current system datetime ,as returned by the mock object
In the above example we are setting the expected behaviour for the GetDateofJoining() method.We are passing the return value to the Returns() method.
Using Moq for unit testing our code provides a means to test otherwise difficult to test code. Following are some of the advantages of using a mocking framework such as Moq:
While unit testing our code we need to segregate dependencies from the code we are testing.If we are testing class A which depends on class B then we can mock the class B .By mocking class B we will be able to test just the class A without needing to test its dependencies as well.
We sometimes need to unit test methods which consists of hard to produce scenarios.Common example of such scenarios are:
- Throwing a specific error on a particular condition.Example of such a condition is a network error.
- Accessing an unavailable resource.Suppose if some external resource such as database is not available in the development environment then the only way to test a method accessing the database is by creating a mock object of the data access class.
Tests execute faster as we are accessing the mock object instead of some external resource such as database.
We don’t need to repeat the mocking code if use a mocking framework such as Moq.While if we write the mock classes and methods manually we need to repeat the same code which is a violation of the Don’t Repeat Yourself or DRY principle.
To provide mock implementation of a non existent class : While developing our application we often come across scenarios where some class is not yet developed.We usually throw NotImplementedException in such a scenario.To avoid this situation and still run our application we can mock the non-existent class.Once the original class is developed and tested we just need to replace the mock object with the original class.
Leave a Reply