如何为AutoFixture添加特定类型对象的后处理步骤以满足嵌套属性规则
用AutoFixture生成符合Number一致性规则的Root对象
当然可以,下面给两种实用的实现方式:
方法一:直接定制Root的生成逻辑(简单快速)
利用AutoFixture的Customize扩展方法,在Root对象生成后,用同一个Number值替换嵌套对象的对应属性:
var fixture = new Fixture(); fixture.Customize<Root>(config => config .Do(root => { // 复用Root自动生成的Number值 var sharedNumber = root.Number; root.Nested1 = fixture.Build<Nested1>().With(n => n.Number, sharedNumber).Create(); root.Nested2 = fixture.Build<Nested2>().With(n => n.Number, sharedNumber).Create(); }) ); // 生成符合规则的Root对象 var root = fixture.Create<Root>(); // 验证规则:三个Number值完全一致 Debug.Assert(root.Number == root.Nested1.Number && root.Number == root.Nested2.Number);
这种方式无需额外定义类,适合单测试场景快速实现需求。
方法二:自定义生成器(全局复用)
如果多个测试都需要遵循这个规则,可以实现ISpecimenBuilder接口,拦截Root类型的生成请求,统一生成符合规则的对象:
1. 定义自定义生成器
public class RootWithMatchingNumbersBuilder : ISpecimenBuilder { public object Create(object request, ISpecimenContext context) { // 只处理Root类型的生成请求 if (request is Type type && type == typeof(Root)) { // 生成一个共享的Number值 var sharedNumber = context.Create<string>(); // 构建符合规则的Root对象 return new Root { Number = sharedNumber, // 若嵌套对象有其他属性需要自动填充,用context.Create生成后再覆盖Number Nested1 = context.Create<Nested1>() with { Number = sharedNumber }, Nested2 = context.Create<Nested2>() with { Number = sharedNumber } }; } // 非Root类型的请求,交给AutoFixture默认处理 return new NoSpecimen(); } }
2. 使用自定义生成器
var fixture = new Fixture(); // 将自定义生成器添加到AutoFixture的定制链中 fixture.Customizations.Add(new RootWithMatchingNumbersBuilder()); // 生成符合规则的Root对象 var root = fixture.Create<Root>(); // 验证规则成立 Debug.Assert(root.Number == root.Nested1.Number && root.Number == root.Nested2.Number);
这种方式的优势是一次定义,全局复用,适合大型测试套件的场景。
内容的提问来源于stack exchange,提问作者Aleksey Usatov
相关产品推荐
相关产品推荐

