Search code examples
cqrsmediatr

How to instantiate Mediatr as part of a Unit Test?


I am trying to build an xUnit Test project for an MVC Core 2.2 Application that is based on the CQRS/ES pattern. I utilize MediatR as part of my CQRS/ES pattern in the MVC application.

In one of my commands which I would like to test, I inject MediatR to publish an event once a customer record has been updated. Kind of like this:

public class UpdateCustomerCommandHandler : IRequestHandler<UpdateCustomerCommand>
{
    public IMediator Mediator { get; set;  }

    public UpdateCustomerCommandHandler(IMediator mediator)
    {
        Mediator = mediator;
    }

    public Task<Unit> Handle(UpdateCustomerCommand request, CancellationToken cancellationToken)
    {
        //do some stuff

        Mediator.Publish(new CustomersChanged());

        return Task.FromResult(new Unit());
    }
}

When writing a unit test for this command, I obviously also must create an instance of MediatR (or a mockup) which I then pass to to the command during test execution.

[Fact]
public async void UpdateCustomerCommand_CustomerDataUpdatedOnDatabase()
{
    //Arange

    var mediator = new Mediator(); // doesn't work that way..

    UpdateCustomerCommand command = new UpdateCustomerCommand();
    UpdateCustomerCommandHandler handler = new UpdateCustomerCommandHandler(mediator);

    //Act
    Unit x = await handler.Handle(command, new System.Threading.CancellationToken());

    //Asert
    //Do the assertion
}

However, instanciating MediatR (outside of the MVC application, where I can utilize the existing dependency injection implementation) seems to be not that simple and frankly speaking I actually do not understand how I can do in my test method.

I understand that I potentially could use a dependency injection framework for which MediatR already provides an implementation (Ninject, etc.), but I actually do not want to use any other third party libraries in my unit tests apart from MediatR, just for the sake of creating an instance.

Is there a simpler way to instantiate MediatR which I might have overseen?


Solution

  • You're on the right lines with or a mockup - you need to mock the IMediator

    There's a few mocking libraries out there:

    • Moq
    • FakeItEasy
    • NSubstitute

    Moq is one of the most popular, so, using your test as an example:

    [Fact]
    public async void UpdateCustomerCommand_CustomerDataUpdatedOnDatabase()
    {
        //Arrange
        var mediator = new  Mock<IMediator>();
    
        UpdateCustomerCommand command = new UpdateCustomerCommand();
        UpdateCustomerCommandHandler handler = new UpdateCustomerCommandHandler(mediator.Object);
    
        //Act
        Unit x = await handler.Handle(command, new System.Threading.CancellationToken());
    
        //Assert
        //Do the assertion
    
        //something like:
        mediator.Verify(x=>x.Publish(It.IsAny<CustomersChanged>()));
    }