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?
What is MediatR? MediatR is an implementation of the mediator pattern. It is a behavioural software design pattern that helps you to build simpler code by making all components communicate via a "mediator" object, instead of directly with each other.
MediatR Requests are very simple request-response style messages, where a single request is synchronously handled by a single handler (synchronous from the request point of view, not C# internal async/await). Good use cases here would be returning something from a database or updating a database.
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 is one of the most popular, so, using your test as an example:
[Fact]
public async void UpdateCustomerCommand_CustomerDataUpdatedOnDatabase()
{
//Arange
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());
//Asert
//Do the assertion
//something like:
mediator.Verify(x=>x.Publish(It.IsAny<CustomersChanged>()));
}
To expand on the accepted answer, if you absolutely need to test interaction between two services using MediatR, you can always moq each publish/handler pair using callbacks:
_mediator = new Mock<IMediator>();
_mediator.Setup(m => m.Publish(It.IsAny<YourNotification>(), It.IsAny<CancellationToken>()))
.Callback<YourNotification, CancellationToken>((notification, cToken) =>
_yourHandlerService.Handle(notification, cToken));
The above code, basically says if _mediator gets YourNotification
via Publish
method, then it will forward it to _yourHandlerService
via Handle
method. You can repeat that Setup
for each type of mediator INotification
you want to handle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With