1

I'm trying to mock a handler with Moq. This handler takes a parameter of type bool to filter out active customers and non active customers.

The handler is used in my service:

    public async Task<IEnumerable<CustomerDto>> GetCustomers(bool active)
    {
        return _mapper.Map<IEnumerable<CustomerDto>>(await _mediatr.Send(new GetCustomersQuery { Active = active }));
    }

My handler looks like this:

public class GetCustomersHandler : IRequestHandler<GetCustomersQuery, IEnumerable<Customer>>
{

    private readonly ICustomersRepository _repository;

    public GetCustomersHandler(ICustomersRepository repository)
    {
        _repository = repository;
    }

    public async Task<IEnumerable<Customer>> Handle(GetCustomersQuery request, CancellationToken cancellationToken)
    {
        return await _repository.GetCustomers(request.Active);
    }
}

My test:

    [Fact]
    public async Task CustomersService_GetCustomers_ActiveReturnsOnlyActiveCustomers()
    {
        var result = await _service.GetCustomers(true);

        // asserts to test result
    }

My mock code:

        var mockMediatr = new Mock<IMediator>();
        mockMediatr.Setup(m => m.Send(It.IsAny<GetBlockedCustomersAndGroupsQuery>(), It.IsAny<CancellationToken>()))
            .Returns(async (bool active) => 
                await _getBlockedCustomersAndGroupsHandler.Handle(new GetBlockedCustomersAndGroupsQuery { Active = active }, new CancellationToken())); ---> How can I pass my bool parameter here?

EDIT: I don't have the mock code for the mediator in my test (for reuse). I want to be able to test both scenarios where true is passed and false is passed. If I try it like mentioned above, I get this error: "Invalid callback. Setup on method with 2 parameter(s) cannot invoke callback with different number of parameters (1)".

I can mock the mediator in the test code and pass that:

mockMediatr.Setup(m => m.Send(It.IsAny<GetBlockedCustomersAndGroupsQuery>(), It.IsAny<CancellationToken>()))
            .Returns(async () => 
                await _getBlockedCustomersAndGroupsHandler.Handle(new GetBlockedCustomersAndGroupsQuery { Active = true }, new CancellationToken()));

But here I'm not able to reuse it in the second test (with Active = false) and I have some duplicated code. Is there a way to do it like this or do I need to put the mock code inside the test code?

  • You should express your problem: What did you expect, and what happend? And explain what you did to bring both together. – Rico-E Mar 23 '20 at 10:36
  • @Rico-E I hope this clarifies what I want to know :) – Dorien Brugmans Mar 23 '20 at 11:40
  • Much better, thanks – Rico-E Mar 23 '20 at 16:05
  • Did you tried to mock nothing except maybe repository? – Fabio Mar 23 '20 at 22:42
  • Just imagine what you gonna need to change when you decide to get rid of MediaR. (You probably will after some time ;)) – Fabio Mar 23 '20 at 22:43
  • I mocked my repository, which I passed into my handlers. My repo uses lists I have setup with test data. Also my mediatR is mocked (and passed into my service). And my service uses the queries and the handlers but is not mocked. Not a great fan of MediatR? :P – Dorien Brugmans Mar 24 '20 at 08:21

1 Answers1

2

I found how I can access the data that is passed.

mockMediatr.Setup(m => m.Send(It.IsAny(), It.IsAny())) .Returns(async (GetBlockedCustomersAndGroupsQuery q, CancellationToken token) => await _getBlockedCustomersAndGroupsHandler.Handle(new GetBlockedCustomersAndGroupsQuery { Active = q.Active}, token));