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

如何让AutoFixture自动解析Mock中的方法调用?

解决AutoFixture自动解析自定义IServiceProvider的Mock实例问题

问题核心

你自定义的IServiceProvider接口不在AutoMoq默认处理逻辑中,所以AutoFixture不会自动配置它的Resolve<T>方法返回已冻结的Mock实例,导致必须手动编写Setup逻辑,多层工厂场景下会格外繁琐。

解决方案

通过自定义AutoFixture的ICustomization,让IServiceProvider的Mock自动返回Fixture中对应类型的实例(包括已冻结的Mock),实现类似常规DI的便捷性。

1. 实现ServiceProvider自定义规则

创建一个Customization类,自动配置IServiceProvider的Mock行为:

public class ServiceProviderCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        var mockProvider = fixture.Freeze<Mock<IServiceProvider>>();
        // 配置Resolve<T>方法,返回Fixture中对应类型的实例
        mockProvider.Setup(p => p.Resolve<It.IsAnyType>())
                    .Returns((Type type) => fixture.Create(type));
    }
}

2. 在普通Fact测试中使用

修改原有测试代码,添加自定义规则:

[Fact]
public void Test()
{
    var fixture = new Fixture()
        .Customize(new AutoMoqCustomization { ConfigureMembers = true })
        .Customize(new ServiceProviderCustomization());

    var service = fixture.Freeze<Mock<IService>>();
    service.Setup(x => x.Fail()).Throws(new Exception("Failed"));

    var sut = fixture.Create<SystemUnderTest>();
    Assert.Throws<Exception>(() => sut.Test());
}

3. 配合DataAttribute实现极简写法

如果你想使用期望的[AutoMoq]风格属性,可以创建一个组合了AutoMoq和自定义规则的DataAttribute:

public class AutoMoqWithServiceProviderAttribute : AutoDataAttribute
{
    public AutoMoqWithServiceProviderAttribute()
        : base(() => new Fixture()
            .Customize(new AutoMoqCustomization { ConfigureMembers = true })
            .Customize(new ServiceProviderCustomization()))
    {
    }
}

之后就能用你想要的简洁写法完成测试:

[Theory, AutoMoqWithServiceProvider]
public void Test([Frozen]Mock<IService> service, SystemUnderTest sut)
{
    service.Setup(x => x.Fail()).Throws(new Exception("Failed"));
    Assert.Throws<Exception>(() => sut.Test());
}

原理说明

这个自定义规则会先冻结IServiceProvider的Mock实例,然后配置它的泛型Resolve<T>方法:当调用Resolve<T>时,会委托给Fixture的Create(type)方法获取实例。由于AutoMoq的特性,Fixture会自动把已冻结的Mock<T>的Object实例作为T类型的返回值,所以无论多少层工厂解析,只要你冻结了对应的Mock,Resolve都会返回正确的实例,无需手动配置每一个Resolve调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:35:34