moq for mediator using generics in unit testing

2.7k views Asked by At

I use cqrs and mediatr in .net core 3 webapi project. I want to unit test controller methods behavior, so when the method is called, mediator does it work as expected. I wrote testing code for one method and it works fine. Many code is omitted for brevity, I only used code which causes the error. So, working test:

        var mockScrapedAd = ScrapedAd.CreateMockAd(DateTime.Now); //result of controller method

         mediatrMock.Setup(m =>
             m.Send(It.IsAny<QueryDetails>(),
                 It.IsAny<CancellationToken>())).
             ReturnsAsync(() => mockScrapedAd); //mock for mediator,
         // so when something with QueryDetails type is called, it should return result from above

        var ret = await controller.Details(0); //should send QueryDetails via Mediatr

        Assert.Equal(mockScrapedAd, ret.Value); //all good?

       mediatrMock.Verify(x => x.Send(It.IsAny<QueryDetails>(), //was it called at all?
           It.IsAny<CancellationToken>()));

This test works, but I will have to duplicate code for each controller method. The only thing that changes here is type of mediatr request (QueryDetails here) and mock for return. So I tried to use generic method like here:

    async Task TestBase<TK,K>(TK expectedResult,Func<Task<ActionResult<TK>>> callControllerMethod)
    {

        mediatrMock.Setup(m =>
            m.Send(It.IsAny<K>(),
                It.IsAny<CancellationToken>())).ReturnsAsync(() => expectedResult);

        var ret = await callControllerMethod();

        Assert.Equal(expectedResult, ret.Value);

       mediatrMock.Verify(x => x.Send(It.IsAny<K>(),
           It.IsAny<CancellationToken>()));

    }

And the test suite will be easier:

     var mockScrapedAd = ScrapedAd.CreateMockAd(DateTime.Now);            

        await TestBase<ScrapedAd,QueryDetails>(mockScrapedAd, async () => await controller.Details(0));

Basically all I changed is moved QueryDetails inside generic method. Mediator fails to recognize it and response is not called. What's wrong here?

0

There are 0 answers