IMediator Mock returns null when I set up it in test
Here is my code:
public sealed class BulkAddStockConditionItemCommandHandler : IRequestHandler<BulkAddStockConditionItemCommand,
UserStockConditionSetsEntity>
{
private readonly IMediator _mediator;
public BulkAddStockConditionItemCommandHandler(IMediator mediator)
{
_mediator = mediator;
}
public async Task<UserStockConditionSetsEntity> Handle(BulkAddStockConditionItemCommand request,
CancellationToken cancellationToken)
{
var conditionalRiskAgreements = new ConditionalRiskAgreementEntity(_userService.CustomerIsin);
var addRes = await _mediator.Send(new AcceptConditionalRiskAgreementCommand(), cancellationToken);
if (addRes == null) throw new Exception();
//...code removed for brevity
}
}
I inject the IMediator
into my constructor and I need the addRes
not be NULL
in my unit test scenario, so here you can see my test scenario:
public async void BulkAddStockConditionItemCommand_when_StockConditionSet_is_null()
{
//arrange
var condition = new ConditionalRiskAgreementEntity(RandomIsin);
var mediator = new Mock<IMediator>();
mediator.Setup(i => i.Send(It.IsAny<ConditionalRiskAgreementEntity>(), It.IsAny<System.Threading.CancellationToken>())).ReturnsAsync(Task.FromResult<object>(condition));
BulkAddStockConditionItemCommand command = new BulkAddStockConditionItemCommand(data);
BulkAddStockConditionItemCommandHandler handler = new BulkAddStockConditionItemCommandHandler(mediator.Object, userservice.Object, repoacc.Object, CacheableRepository.Object);
//Act
var caughtException = await Assert.ThrowsAsync<Exception>(() => handler.Handle(command, new System.Threading.CancellationToken()));
//Assert
Assert.IsType<Exception>(caughtException);
}
I set up the IMediator
as but when I run the test it returns null
instead of condition
variable. Why?
Based on the shown code, the subject under test uses AcceptConditionalRiskAgreementCommand
//...
var addRes = await _mediator.Send(new AcceptConditionalRiskAgreementCommand(), cancellationToken);
//...
but in the test the mocked mediator is setup to expect ConditionalRiskAgreementEntity
//...
mediator.Setup(i => i.Send(It.IsAny<ConditionalRiskAgreementEntity>(), It.IsAny<System.Threading.CancellationToken>()))
.ReturnsAsync(Task.FromResult<object>(condition));
//...
The mock will return null by default when the argument matchers do not match in the invoked member.
There is no need to return Task.FromResult<object>(condition)
in ReturnsAsync
since that will wrap whatever you pass in a Task
First I suggest you refactor the test to use async Task
instead of async void
and then update the mock to expect the actual argument types used in the subject under test.
public async Task BulkAddStockConditionItemCommand_when_StockConditionSet_is_null() {
//Arrange
var condition = new ConditionalRiskAgreementEntity(RandomIsin);
var mediator = new Mock<IMediator>();
mediator
.Setup(i => i.Send(It.IsAny<AcceptConditionalRiskAgreementCommand>(), It.IsAny<System.Threading.CancellationToken>()))
.ReturnsAsync(condition);
BulkAddStockConditionItemCommand command = new BulkAddStockConditionItemCommand(data);
BulkAddStockConditionItemCommandHandler handler = new BulkAddStockConditionItemCommandHandler(mediator.Object, userservice.Object, repoacc.Object, CacheableRepository.Object);
//Act
var caughtException = await Assert.ThrowsAsync<Exception>(() => handler.Handle(command, new System.Threading.CancellationToken()));
//Assert
Assert.IsType<Exception>(caughtException);
}