You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试控制器时MediatR返回Null问题求助

MediatR Mock返回Null的问题解决方法

你的问题出在Moq的参数匹配逻辑上:

在测试代码里,你给MediatR的Send方法Setup时用的是自己创建的query实例:

_mediator.Setup(x => x.Send(query, It.IsAny<CancellationToken>())).ReturnsAsync(mappedAuthor);

但控制器内部会新建一个完全独立的GetAuthorQuery对象:

var query = new GetAuthorQuery(authorId);

Moq默认对引用类型参数采用引用相等匹配,这两个实例不是同一个对象,所以Mock的Setup不会被触发,Send方法自然返回默认的Null。

解决办法(推荐第一种)

1. 使用参数条件匹配

把Setup里的query替换成按属性值匹配的条件,只要Query的AuthorId和测试用的ID一致就触发:

// 替换原来的MediatR Setup代码
_mediator.Setup(x => x.Send(
    It.Is<GetAuthorQuery>(q => q.AuthorId == author.Id), 
    It.IsAny<CancellationToken>()
)).ReturnsAsync(mappedAuthor);

2. 给GetAuthorQuery实现值相等

如果你的Query对象需要经常按值匹配,可以重写它的Equals和GetHashCode方法:

public class GetAuthorQuery : IRequest<AuthorDto>
{
    public int AuthorId { get; }

    public GetAuthorQuery(int authorId)
    {
        AuthorId = authorId;
    }

    public override bool Equals(object obj)
    {
        return obj is GetAuthorQuery query && AuthorId == query.AuthorId;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(AuthorId);
    }
}

这样Moq就能正确识别两个属性相同的Query实例是相等的,原来的Setup代码就可以正常工作。

额外优化

你的测试代码里有一行多余的Setup:

_authorRepository.Setup(r=>r.GetAuthor(author.Id)).ReturnsAsync(author);

控制器里根本没有直接依赖IAuthorRepository,而是通过MediatR发送Query,所以这个Setup完全没用,可以删掉,避免混淆。

修改后的完整测试方法:

[Test]
public async Task GetAuthor_Returns_Ok()
{
    var author = fixture.Build<Author>().Create();
    var mappedAuthor= _mapper.Map<AuthorDto>(author);

    var controller = new AuthorController(_mediator.Object);

    // 用条件匹配设置MediatR
    _mediator.Setup(x => x.Send(
        It.Is<GetAuthorQuery>(q => q.AuthorId == author.Id), 
        It.IsAny<CancellationToken>()
    )).ReturnsAsync(mappedAuthor);

    var result = await controller.GetAuthor(author.Id);
    var obj = result as ObjectResult;

    Assert.AreEqual(200, obj.StatusCode);
}

内容的提问来源于stack exchange,提问作者Sev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 15:32:46