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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 18:54:03