Reputation: 1573
I am building generic test helper method to verify whether a method is called in the mock with the given type. In my example I am mocking IMediator
from the library MediatR. For mocking I am using Moq library
Let's see the code. For the sake of simplicity I made a "dummy" service and a corresponding test, to only focus on the problem. My production code:
public class Service
{
private readonly IMediator _mediator;
public Service(IMediator mediator)
{
_mediator = mediator;
}
public void SendQuery()
{
_mediator.Send(new GetAllProductsQuery());
}
}
And the corresponding test:
[Fact]
public void WhenSendQueryCalled_ThenGetAllProductsQuerySend()
{
//Arrange
var mockedMediator = new Mock<IMediator>();
var service = new Service(mockedMediator.Object);
//Act
service.SendQuery();
//Assert
CheckThatRequestSentViaMediator<GetAllProductsQuery>(mockedMediator);
}
private void CheckThatRequestSentViaMediator<TRequest>(Mock<IMediator> mockedMediator) where TRequest : class
{
mockedMediator.Verify(mock => mock.Send(It.IsAny<TRequest>(), It.IsAny<CancellationToken>()), Times.Once);
}
My assert method does fail, unexpectedly, with the following reason:
Moq.MockException:
Expected invocation on the mock once, but was 0 times: mock => mock.Send(It.IsAny<GetAllProductsQuery>(), It.IsAny<CancellationToken>())
Performed invocations:
Mock<IMediator:1> (mock):
On the other hand, If I specify the type directly in the verification method, the test passes. The passing assert method looks as the following:
private void CheckGetAllProductsQuerySentViaMediator(Mock<IMediator> mockedMediator)
{
mockedMediator.Verify(mock => mock.Send(It.IsAny<GetAllProductsQuery>(), It.IsAny<CancellationToken>()), Times.Once);
}
It looks quite strange to me, since the second assert method works flawlesly. But if I use the generic type parameter and pas it on to the verify method, it fails. What am I doing wrong? Am I not aware of some important underlying behaviour of C#/.NET.Core? Thanks for the help!
Upvotes: 2
Views: 614
Reputation: 9509
It seems that the problem is with your constraint where TRequest : class
.
If you look at the IMediator
you will find two methods:
It is confusing to moq
to really figure out which override to use. Try being really explicit with the types to really point to the right method, for example:
private static void CheckThatRequestSentViaMediator<T>(Mock<IMediator> mediator)
where T : IRequest<T>
or
private static void CheckThatRequestSentViaMediator<T>(Mock<IMediator> mediator) where T : class
{
mediator.Verify(mock => mock.Send(It.IsAny<IRequest<T>>(), It.IsAny<CancellationToken>()), Times.Once);
}
Upvotes: 1