如何用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
相关产品推荐
相关产品推荐

