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

使用Xunit与Moq单元测试PersonService时Mock不返回预设值问题

问题原因

你的测试用例中Moq Setup未生效,返回默认值0是以下几个匹配规则不满足导致的:

  • Transaction参数实例不匹配:业务代码中调用PostPersonAsync时传入的是_unitOfWork.Transaction属性,而你测试用例中Setup时传入的是自己手动创建的_IDbTransaction.Object实例,两个实例不是同一个对象,Moq默认严格匹配参数引用,匹配失败就会返回类型默认值0。
  • PersonDto参数引用不匹配:如果PersonDto没有重写Equals方法,Moq会按引用匹配参数。你测试用例中提前Map出来的PersonDto,和业务代码运行时内部Map生成的PersonDto是两个不同的引用对象,也会导致匹配失败。
  • 缺少必要的Mock配置:你没有配置_unitOfWorkMock1的Begin()、Transaction、Connection等成员的返回值,容易触发空引用或者逻辑中断。
解决方案

按以下步骤修改测试用例即可:

  1. 配置IUnitOfWork的Transaction属性,返回你创建的事务Mock实例,保证参数实例一致
  2. 调整PostPersonAsync的Setup参数匹配规则,用It.Is<T>或者It.IsAny<T>替代固定实例匹配
  3. 测试方法改为异步写法,避免.Result导致的死锁问题
  4. 补全必要的成员Mock配置,保证业务逻辑可以正常跑完

修改后的测试用例代码

[Fact]
public async Task PostPersonAsync_Should_SavePerson()
{
    //Arrange
    var dbTransactionMock = new Mock<IDbTransaction>();
    var dbConnectionMock = new Mock<IDbConnection>();
    var unitOfWorkMock = new Mock<IUnitOfWork>();
    // 补全Connection属性Mock,避免using块报错
    unitOfWorkMock.Setup(s => s.Connection).Returns(dbConnectionMock.Object);
    // 配置Transaction返回我们创建的事务实例,保证参数匹配
    unitOfWorkMock.Setup(s => s.Transaction).Returns(dbTransactionMock.Object);
    
    var expectedAffectedRows = 5;
    // 参数用It.Is匹配,只要是符合预期的PersonDto即可,也可以加字段校验规则
    unitOfWorkMock.Setup(s => s.PersonRepository.PostPersonAsync(
        It.Is<PersonDto>(d => d.Name == PersonServiceData.PersonModel.Name 
            && d.Age == PersonServiceData.PersonModel.Age), // 按需补充你要校验的DTO字段
        dbTransactionMock.Object))
        .ReturnsAsync(expectedAffectedRows);
    
    // 补全其他方法的Mock配置
    unitOfWorkMock.Setup(s => s.OpenConnection());
    unitOfWorkMock.Setup(s => s.Begin());
    unitOfWorkMock.Setup(s => s.Commit());
    unitOfWorkMock.Setup(s => s.CloseConnection());
    
    var target = new PersonService(unitOfWorkMock.Object, _mapper);

    //Act
    var result = await target.PostPersonAsync(PersonServiceData.PersonModel);

    //Assert
    Assert.Equal(expectedAffectedRows, result);
    // 可选补充校验:验证事务行为是否符合预期
    unitOfWorkMock.Verify(s => s.Commit(), Times.Once);
    unitOfWorkMock.Verify(s => s.Rollback(), Times.Never);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 01:06:03