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

