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);
}