This post was originally published here.
C# Unit Tests with Mocks provide an easy way of reducing unwanted dependencies when writing unit tests. One of the best and shortest definition for mocking is mocking is creating objects that simulate the behavior of real objects. - StackOverflow.
Prologue
However, when talking about writing unit tests I would strongly advise to not change the implementation itself. Rather, think about how you can test it easily before start writing the implementation. The very best approach for unit-testing would be Test-Driven-Development (TDD) anyway, but I understand that many struggles with this methodology. Especially when starting with tests in general. Always Keep in mind that the S.O.L.I.D Framework helps you a lot when writing unit tests.
Moq Framework
Moq is an open-source framework which can be found on GitHub. When start using Moq make sure you always install the very latest version. Moq is usable with any test runner like vstest, xunit, nunit etc. When using Moq or any other mocking framework keep following restrictions in mind. You can not mock:
- Static class/methods.
- Extensions Methods.
- Non-virtual methods (except there is an interface).
For this blog post, I have used my link-reader repository. This project is written with dotnet core 2.1.
However, you can easily use a newer version of dotnet core if you want. You can see that in this particular case it is necessary to nest multiple mocks within each other. You can configure that one mock mocks a method and return another mock object. To generate a mock you just have to create a new Mock object and set the type. As you see Moq uses generics very heavily.
var moq = new Mock<IWebRequest>();
When you look at the IWebRequest definition you'll see that the interface has a Create method that all classes have to implement. Therefore, we can easily mock this method in our case by using the Setup.
moq.Setup(_ => _.Create(It.IsAny<string>())).Returns(moqHttpWebRequest.Object);
When you want to mock a method with parameters you can work with the It.IsAny() option. In the example above all string values are allowed. Of course, you can strict this up and allow only specific values to work with. To work with mocks you have to use the mock.Object property. This property is the actual mock implementation of the source.
var webRequest = moq.Object.Create(test);
The line above returns the moqHttpWebRequest.Object, because that's the way we have set up the mock behavior.
Customizing Mock Behavior
Moq provides different ways to set up the mock - MockBehavior.Strict
- MockBehavior.Loose
- CallBase = true
- { DefaultValue = DefaultValue.Mock }
- MockBehavior.Strict and { DefaultValue = DefaultValue.Mock }
Verification
When you are using the verification from a mock instance by calling moq.Verify() it does check if all set up methods are called. You can check all Moq Setups without any Verifiable declaration by using the moq.VerifyAll() method on the mocked object. Happy mocking and testing.
Top comments (0)