AutoFixture中PostProcessor导致自定义ISpecimenCommand执行两次问题求助
解决AutoFixture自定义输出重复打印的问题
我尝试实现ICustomization,将AutoFixture生成的Fixture值输出到控制台,以辅助诊断夜间构建测试中的间歇性失败。但目前遇到每个值被输出两次的问题,且找到的示例均针对特定类型处理,我需要能处理所有类型的通用实现。以下是LINQPad中的简化代码及重复输出结果:
void Main() { var fixture = new Fixture(); fixture.Customize(new CustomCustomisation()); fixture.Create<double>(); } public class CustomCustomisation : ICustomization { public void Customize(IFixture fixture) { var engine = ((Fixture)fixture).Engine; fixture.Customizations.Add(new Postprocessor(engine, new LogSpecimenCommand())); } } public class LogSpecimenCommand : ISpecimenCommand { public void Execute(object specimen, ISpecimenContext context) { if (specimen == null || specimen is NoSpecimen) return; Console.WriteLine($"SPECIMEN: {specimen}"); } }
输出结果:
SPECIMEN: 213 SPECIMEN: 213
问题原因
重复输出的核心原因是递归调用:你将Postprocessor的构建器设为Fixture的整个Engine,再把这个Postprocessor添加到Customizations集合中。当AutoFixture创建标本时,会先遍历Customizations中的构建器,调用你的Postprocessor,而它又会委托给Engine处理请求;Engine在处理时会再次遍历Customizations,导致Postprocessor被第二次调用,最终触发两次日志输出。
通用解决方案
要实现全类型的日志记录,不需要包裹整个Engine,而是创建一个自定义的ISpecimenBuilder,插入到Customizations的最前端,让所有标本请求都经过它,在获取到标本后统一记录。
修改后的代码
void Main() { var fixture = new Fixture(); fixture.Customize(new CustomCustomisation()); fixture.Create<double>(); } public class CustomCustomisation : ICustomization { public void Customize(IFixture fixture) { // 将日志构建器插入到Customizations最前面,确保所有请求都经过它 fixture.Customizations.Insert(0, new LoggingSpecimenBuilder()); } } public class LoggingSpecimenBuilder : ISpecimenBuilder { public object Create(object request, ISpecimenContext context) { // 委托给后续的构建器创建标本 var specimen = context.Resolve(request); // 过滤无效标本并记录有效结果 if (specimen is not NoSpecimen and not OmitSpecimen and not null) { Console.WriteLine($"SPECIMEN: [{request}] -> {specimen}"); } return specimen; } }
关键说明
LoggingSpecimenBuilder:实现ISpecimenBuilder接口,通过context.Resolve(request)让AutoFixture的默认流程处理标本创建,获取结果后再执行日志记录,彻底避免递归问题。- 插入位置:使用
Insert(0, ...)将日志构建器放在Customizations的最前面,确保所有类型的标本请求都会经过它,实现全类型覆盖。 - 标本过滤:增加了
OmitSpecimen的判断,避免记录AutoFixture内部的跳过标记,让日志更干净。
修改后,每个生成的标本只会被记录一次,且支持所有类型的通用处理。
内容的提问来源于stack exchange,提问作者dp.collins
相关产品推荐
相关产品推荐

