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

使用Moq模拟IRepo时为何返回未映射的Address1属性?

问题原因与修复方案

问题根源

你当前的测试完全没有调用真实的Repo类逻辑,而是用Moq创建了IRepo的模拟对象。你在Setup中明确指定Execute方法返回自己手动创建的expectedResult——这个对象里你主动给Address1赋了值,所以模拟对象必然返回包含该属性值的实例,和真实Repo中“不映射Address1”的逻辑没有任何关联。

简单来说:你测试的是Moq的模拟行为,而非真实Repo的业务逻辑。

修复方案

方案1:测试真实Repo的映射逻辑(需隔离数据库)

要验证真实Repo中“仅映射ID和Name,Address1保持默认值”的逻辑,需要先把数据库操作抽象为独立接口,再用Moq模拟数据库返回的数据,让真实Repo依赖模拟的数据库接口,从而在不连接真实数据库的情况下测试Repo的映射逻辑。

步骤如下:

  1. 抽象数据库访问接口:
public interface IDbAccess
{
    (int Id, string Name) GetModelData(DateTime date);
}
  1. 修改Repo依赖该接口:
public class Repo : IRepo
{
    private readonly IDbAccess _dbAccess;

    public Repo(IDbAccess dbAccess)
    {
        _dbAccess = dbAccess;
    }

    public Model Execute(DateTime date)
    {
        var dbData = _dbAccess.GetModelData(date);
        return new Model()
        {
            ID = dbData.Id,
            Name = dbData.Name
            // 不设置Address1,保持默认值null
        };
    }
}
  1. 编写单元测试:
[Test]
public void Repo_Execute_OnlyMapsIdAndName()
{
    // 模拟数据库返回的数据
    var mockDbAccess = new Mock<IDbAccess>();
    mockDbAccess.Setup(d => d.GetModelData(It.IsAny<DateTime>()))
                .Returns((1, "Username"));

    // 实例化真实Repo,注入模拟的数据库访问组件
    var repo = new Repo(mockDbAccess.Object);
    var result = repo.Execute(DateTime.Now);

    // 验证映射结果
    Assert.AreEqual(1, result.ID);
    Assert.AreEqual("Username", result.Name);
    Assert.IsNull(result.Address1); // 验证Address1未被赋值
}

方案2:明确测试目标(若无需测试真实Repo)

如果你的场景不需要测试真实Repo,只是想验证依赖IRepo的其他组件逻辑,但你当前没有服务类,那这种测试其实没有实际业务价值——它只是在验证Moq的设置是否正确。此时你应该重新明确测试目标:单元测试的核心是验证真实业务逻辑,而非模拟框架的行为。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 14:52:36