Writing unit tests is an integral part of most software developers work. We spend a lot of time writing them so it's important that we use tools and practices that makes this as quick and simple as possible. In this article I will show you how to save time by automatically mocking your services' dependencies in unit tests.

Introduction

If you work with IoC via constructor dependency injected services, chances are your services looks a lot like this:

public class CustomerService { private readonly ILogger _logger; private readonly ISettings _settings; private readonly IUnitOfWork _unitOfWork; private readonly IAnotherDependency _anotherDependency; public CustomerService( ILogger logger, ISettings settings, IUnitOfWork unitOfWork, IAnotherDependency anotherDependency ) { _logger = logger; _settings = settings; _unitOfWork = unitOfWork; _anotherDependency = anotherDependency; } //... }

...and your unit tests like this:

[Fact] public CreateNewCustomerSuccessfully() { //Define mock objects var loggerMock = new Mock<ILogger>(); var settingsMock = new Mock<ISettings>(); var unitOfWorkMock = new Mock<IUnitOfWork>(); var anotherDependencyMock = new Mock<IAnotherDependency>(); //Your Moq .Setup are defined here.. //... //Create service to test var service = new CustomerService( loggerMock.Object, settingsMock.Object, unitOfWorkMock.Object, anotherDependencyMock.Object ); //Actual test-case goes here... //... //Your Moq .Verify are defined here... //... }

This is a lot of boilerplate to write for every unit test. Another disadvantage to this is that if you need to change the constructor parameters of your service you'll have a lot of unit tests to change.

Automockers

You can get around this by using an automocker. An automocker automatically creates mock-objects for all constructor parameters of your service. Here is an example of this using Automoqer (which in turn uses the Moq mocking framework):

[Fact] public CreateNewCustomerSuccessfully() { using (var serviceMocker = new AutoMoqer<CustomerService>().Build()) { //Your Moq .Setup are defined here.. //Mocks accessed by serviceMocker.Param<ILogger>().Setup(... //Actual test-case goes here... //Service accessed by serviceMocker.Service //Your Moq .Verify are defined here... //... } }

A unit test such as this does not have to be changed if the constructor parameters of the service (CustomerService in this case) changes.

Advanced usage

You can make exceptions from having Automoqer automatically create Moq-objects from all constructor parameters. This is done by using one of the .With methods available on the AutoMoqer instance. Please note that you won't be able to access these exceptions through the .Param method on the Automoqer-container.

This is how you provide your own instance of a parameter by it's type:

var logger = new TestLogger(); using (var serviceMocker = new AutoMoqer<CustomerService>() .With<ILogger>(logger) .Build()) { //... }

This is how you provide your own instance of a parameter by it's name:

var logger = new TestLogger(); using (var serviceMocker = new AutoMoqer<CustomerService>() .With("logger", logger) .Build()) { //... }

Final thougts

You can read more about Automoqer here https://github.com/rbengtsson/Automoqer or here https://www.nuget.org/packages/Automoqer/