Home > database >  MediatR and CQRS testing. How to verify that handler is called?
MediatR and CQRS testing. How to verify that handler is called?

Time:12-05

I am currently trying to implement MediatR in my project covering with tests. I want to cover if handler's Handle is called when sending a request.

I have this query

public class GetUnitsQuery : IRequest<List<UnitResponse>>
{
}

Handler:

public class GetUnitsHandler : IRequestHandler<GetUnitsQuery, List<UnitResponse>>
{
    readonly IUnitRepository UnitRepository;
    readonly IMapper Mapper;

    public GetUnitsHandler(IUnitRepository unitRepository, IMapper mapper)
    {
        this.UnitRepository = unitRepository;
        Mapper = mapper;
    }

    public async Task<List<UnitResponse>> Handle(GetUnitsQuery request, CancellationToken cancellationToken)
    {
        return Mapper.Map<List<UnitResponse>>(UnitRepository.GetUnits());
    }
}

Send request from the controller:

var result = await Mediator.Send(query);

Any ideas how to test if a Handler is called when specified with a specific Query using MoQ?

CodePudding user response:

I have not used MoQ to check the Received calls to a specific handler. However if I would use Nsubsitute and SpecFlow, I would do something like this in my test.

        var handler = ServiceLocator.Current.GetInstance<IRequestHandler<GetUnitsQuery, List<UnitResponse>>>();
        handler.Received().Handle(Arg.Any<GetUnitsQuery>(), Arg.Any<CancellationToken>());

CodePudding user response:

Like others said in the comments, you don't need to test the internals of Mediator.

Your test boundary is your application, so assuming a controller along the lines of:

public class MyController : Controller 
{
    private readonly IMediator _mediator;

    public MyController(IMediator mediator)
    {
        _mediator = mediator;
    }

    public async IActionResult Index()
    {
        var query = new GetUnitsQuery();

        var result = await Mediator.Send(query);

        return Ok(result);
    }
}

I would verify Mediator is called like this:

public class MyControllerTests 
{
    [SetUp]
    public void SetUp()
    {
        _mockMediator = new Mock<IMediator>();
        _myController = new MyController(_mockMediator.Object)
    }

    [Test]
    public async void CallsMediator()
    {
        // Arranged
        _mockMediator.SetUp(x=> x.Send(It.IsAny<GetUnitsQuery>()))
            .Returns (new List<UnitResponse>());

        // Act
        await _myController.Index();

        // Assert
        _mockMediator.Verify(x=> x.Send(It.IsAny<GetUnitsQuery>()), Times.Once);
    }
}
  • Related