如何覆盖AutoFixture的AutoMoqCustomization自定义接口成员值?
解决AutoMoqCustomization下覆盖单个接口成员返回值的问题
嘿,你的问题出在Test2Customization的实现方式上——直接对Mock<ITest>做定制的写法和AutoMoq的ConfigureMembers自动配置逻辑冲突了,才会导致所有接口成员都返回了相同的"test2"。下面给你几种能达到预期效果的正确方案:
方案一:用Fixture.Build直接定制单个成员
这种方式最直接,不用额外写Customization类,创建实例时指定Test2的返回值就行,其他成员依然由AutoMoq自动生成随机值:
public interface ITest { string Test1(); string Test2(); } class Program { static void Main(string[] args) { var fixture = new Fixture(); // 先启用AutoMoq的自动成员配置 fixture.Customize(new AutoMoqCustomization { ConfigureMembers = true }); // 创建ITest实例时,单独覆盖Test2的返回值 var test = fixture.Build<ITest>() .With(t => t.Test2(), "test2") .Create(); Console.WriteLine($"test1 {test.Test1()}"); Console.WriteLine($"test2 {test.Test2()}"); } }
方案二:修改Test2Customization的实现
如果你还是想通过Customization类封装这个逻辑,别直接去定制Mock<ITest>,应该针对ITest本身来做,利用AutoMoq的API单独设置成员:
public interface ITest { string Test1(); string Test2(); } class Program { static void Main(string[] args) { var fixture = new Fixture(); var customization = new CompositeCustomization( new AutoMoqCustomization { ConfigureMembers = true }, new Test2Customization()); fixture.Customize(customization); var test = fixture.Create<ITest>(); Console.WriteLine($"test1 {test.Test1()}"); Console.WriteLine($"test2 {test.Test2()}"); } private class Test2Customization : ICustomization { public void Customize(IFixture fixture) { // 注册ITest的创建逻辑:先让AutoMoq生成Mock,再覆盖Test2的返回值 fixture.Register(() => { var mock = fixture.Create<Mock<ITest>>(); mock.Setup(t => t.Test2()).Returns("test2"); return mock.Object; }); } } }
或者更简洁的写法,先让AutoMoq自动配置所有成员,再覆盖指定方法:
private class Test2Customization : ICustomization { public void Customize(IFixture fixture) { fixture.Customize<ITest>(c => c.FromFactory(() => { var mock = new Mock<ITest>(); // 启用AutoMoq的自动成员配置 mock.SetupAllProperties(); fixture.Configure(mock); // 单独覆盖Test2的返回值 mock.Setup(t => t.Test2()).Returns("test2"); return mock.Object; })); } }
方案三:用Freeze锁定Mock实例修改
如果需要在多个地方复用这个定制好的Mock,还可以用Freeze功能锁定Mock实例,再修改它的Setup:
public interface ITest { string Test1(); string Test2(); } class Program { static void Main(string[] args) { var fixture = new Fixture(); fixture.Customize(new AutoMoqCustomization { ConfigureMembers = true }); // 冻结Mock<ITest>实例,确保后续创建的ITest都是用这个Mock生成的 var testMock = fixture.Freeze<Mock<ITest>>(); // 覆盖Test2的返回值 testMock.Setup(t => t.Test2()).Returns("test2"); var test = fixture.Create<ITest>(); Console.WriteLine($"test1 {test.Test1()}"); Console.WriteLine($"test2 {test.Test2()}"); } }
这几种方案都能实现你想要的效果:Test1返回AutoFixture自动生成的随机字符串,Test2返回你自定义的"test2"。
内容的提问来源于stack exchange,提问作者Serg046
相关产品推荐
相关产品推荐

