6 tips and tricks for better unit-testing while using the Moq framework

Moq is probably the most known framework for mocking functionality which is then used in your unit-tests. In this article you can find some of my notes about Moq that I wanted to share with you.

Use the SetUp attribute on a method which will run before every unit-test

The SetUp attribute marks a method to run before every unit-test of the current class. This means that inside the marked method you can reset values or setup the mocked class methods to their default. Here is an example:

[SetUp]
public void SetupBeforeEachTest()
{
    // Reset the values of the properties of our DTOs, because they might have be changed from a unit-test
    _testObject.FirstName = "Christos";
    _testObject.LastName = "Monogios";

    // Re-setup the testMethod to return the _testObject because a unit-test might have overridden the method with a custom Setup
    _testMock.Setup(m => m.testMethod).Returns(_testObject);
}

Use the Verify method to check if method was called

When you have complex if-else logic you sometimes want to be sure that only a specific conditional branch is executed. If there are specific methods inside this branch, you can verify if these were called. The other way around can also be verified, if other branches contain specific methods, you can check that these methods were not called.

Here is an example of a positive and a negative check:

//Verify that the testMethod was called exactly one time
_testMock.Verify(p =>
    p.testMethod(It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(1));

// Verify that the otherTestMethod was not called
_testMock.Verify(p =>
    p.otherTestMethod(It.IsAny<string>(), It.IsAny<string>()), Times.Never);

How to test private or protected methods

Moq is not designed for testing private or protected class properties or methods. When unit-testing we are expecting these methods to work as expected and thus only public functions need to be unit-tested (this is my personal opinion). If you desperately need to test such methods, then you can either use reflection, which I do not suggest you to do, or define them as internal. Then, by adding the following line in your AssemblyInfo.cs file you can reference the name of the test project which can then access the internal properties or methods of the current project:

[assembly:InternalsVisibleTo("NameOfTheTestProject")]

The advantage of this way is that the methods still remain hidden from other callers and are only visible to the .dlls you are defining in the InternalsVisibleTo attribute.

For .NET Core projects you either can create the missing the AssemblyInfo.cs file or add the assembly line at the beginning of your files:

using System.Collections.Generic;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Project.Namespace.Tests")]

You can find more information about it here.

How to return null when you are using the Setup method

Returning null from a mocked method can be a valid operation. For example you might want to simulate a DB call which returns no results. However, there is a small caveat while doing that.

The following code

testMock.Setup(m => m.testMethod).Returns(null);

will cause Moq to complain for ambiguous invocation since it does not know which of the different Return methods should call. The following casting will do the trick:

testMock.Setup(m => m.testMethod).Returns((testObject)null);

Unit-test your .NET MVC controller actions

It is possible to call the MVC actions of a .NET controller inside your unit-tests.

When the action returns an ActionResult then you can access and check the returned view by casting it to ViewResult or you can cast the Model object to the actual returned type and assert its properties:

var result = _controller.Save(viewModel) as ViewResult;
var vm = result.Model as TestViewModel;

// The Index method should be returned, so we check for that.
Assert.AreEqual(result.ViewName, "Index");

// The first name should be present in the return object:
Assert.AreEqual(vm.FirstName, "Christos");

We can also test scenarios were the view-model validation found some errors or you want to add a key-value pair to the ViewData object:

// Add a validation error to the ModelState and check if the Model.IsValid() condition works as expected:
_controller.ModelState.AddModelError("FirstNameRequired", "The first name is required!");

// Add a new key-value pair to ViewData, if the key is used inside your action
_controller.ViewData.Add("testKey", "testValue");

Use partial mocks when you need to mock only some of the class methods

This is a very helpful feature when you want to test a class but you do not want to mock all of its methods. In such a case you do not mock the interface, which the class implements, but the class itself. In this blog article you can find a more information about this feature.

comments powered by Disqus