AutoFixture配合Moq使用时[Frozen]标记的Mock未注入SUT问题咨询
问题根源
你当前的注册逻辑是直接为UserManager<User>类型赋值了独立的Mock实例,没有和Mock<UserManager<User>>的创建链路关联。AutoFixture默认不会自动绑定T和Mock<T>的注册规则,你手动注册T的实例后,AutoMoqCustomization的自动Mock创建链路不会触发,就会出现参数里冻结的Mock和SUT注入的实例分属两个不同对象的问题。
解决方案
修改UserManagerCustomization的实现,将Mock<UserManager<User>>的创建逻辑和UserManager<User>的注册逻辑绑定,这样不管是参数注入的Mock还是SUT需要的服务实例,都会复用同一个对象:
public class UserManagerCustomization : ICustomization { public void Customize(IFixture fixture) { // 统一配置所有Mock<UserManager<User>>的初始化逻辑,默认Setup会全局生效 fixture.Customize<Mock<UserManager<User>>>(c => c.FromFactory(() => { var mgr = new Mock<UserManager<User>>(Mock.Of<IUserRoleStore<User>>(), null, null, null, null, null, null, null, null); mgr.Setup(x => x.DeleteAsync(It.IsAny<User>())) .ReturnsAsync(IdentityResult.Success); mgr.Setup(x => x.CreateAsync(It.IsAny<User>(), It.IsAny<string>())) .ReturnsAsync(IdentityResult.Success); mgr.Setup(x => x.UpdateAsync(It.IsAny<User>())) .ReturnsAsync(IdentityResult.Success); mgr.Setup(x => x.AddToRoleAsync(It.IsAny<User>(), It.IsAny<string>())) .ReturnsAsync(IdentityResult.Success); return mgr; })); // 注册UserManager<User>时,直接取当前容器内的Mock实例的Object fixture.Register(() => fixture.Create<Mock<UserManager<User>>>().Object); } }
修改后不需要改动原有测试代码,[Frozen]标记的Mock实例会被优先注入到容器中,SUT构造函数拿到的UserManager<User>就是这个冻结Mock的Object对象,Verify校验就会正常生效。
补充说明
如果你的测试场景需要覆盖默认的Setup,直接在测试用例Act步骤前重写对应Mock的Setup规则即可,新的Setup会覆盖Customization里的默认配置。
内容的提问来源于stack exchange,提问作者Markus Aurelios
相关产品推荐
相关产品推荐

