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

如何用Moq模拟仓储为对象赋值,测试.NET命令处理程序?

如何用Moq模拟仓储为对象属性赋值以完成单元测试

要测试CreateUserCommandHandler的Handle方法,关键是让Mock的IUserRepository在执行CreateUser时,为传入的User对象的Id属性赋值,避免触发方法内的空值异常。利用Moq的**回调(Callback)**功能就能实现这个需求,无需引入额外库。

完整测试代码示例

using Moq;
using Xunit;
using FluentAssertions;

[Fact]
public async Task GivenCorrectCommand_WhenHandlerIsExecuted_ThenEntityShouldContainId()
{
    // Arrange
    var firstName = "FirstName";
    var userRepositoryMock = new Mock<IUserRepository>();
    User capturedUser = null;

    // 模拟CreateUser方法:调用时为User赋值Id,同时捕获该对象用于断言
    userRepositoryMock.Setup(repo => repo.CreateUser(It.IsAny<User>()))
        .Callback<User>(user => 
        {
            capturedUser = user;
            // 根据实际Id类型赋值,这里示例用Guid字符串
            user.Id = Guid.NewGuid().ToString();
        })
        .Returns(Task.CompletedTask); // 异步方法需返回完成状态的Task

    var commandHandler = new CreateUserCommandHandler(userRepositoryMock.Object);

    // Act
    await commandHandler.Handle(firstName);

    // Assert
    // 验证仓储方法是否被正确调用
    userRepositoryMock.Verify(repo => repo.CreateUser(It.Is<User>(u => u.FirstName == firstName)), Times.Once);
    
    // 验证User对象的Id已被赋值
    capturedUser.Should().NotBeNull();
    capturedUser.Id.Should().NotBeNullOrWhiteSpace();
}

特殊情况处理:Id为私有set属性

如果User类的Id是私有set属性,可以通过反射在回调里完成赋值:

.Callback<User>(user => 
{
    capturedUser = user;
    var idProperty = typeof(User).GetProperty("Id", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
    idProperty?.SetValue(user, Guid.NewGuid().ToString());
})

关键说明

  • Moq的Callback方法允许你在Mock方法被调用时执行自定义逻辑,这里就是修改传入的User对象属性。
  • 异步方法CreateUser必须通过Returns(Task.CompletedTask)返回一个已完成的Task,否则会引发异步操作异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:20:27