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?