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

为何AutoFixture自定义后不同属性返回同一实例?

关于AutoFixture中同类型属性生成同一实例问题的原因分析

这问题我之前排查过好几次,核心和AutoFixture的实例复用逻辑以及自定义配置的细节脱不了干系,咱们逐个场景拆解:

1. 简易自定义导致的实例复用

AutoFixture默认的行为是:每次请求一个类型的实例时,都会生成全新的对象——但如果你的自定义配置不小心把类型的创建逻辑变成了「单例模式」,就会触发所有请求都返回同一个实例的问题。

举个典型的错误案例:如果你的自定义代码是这样写的:

// 错误:提前创建好列表,所有请求都返回同一个引用
var preCreatedList = new List<string>();
fixture.Register(() => preCreatedList);

这种情况下,不管AutoFixture要生成多少个List<string>实例,都会拿到同一个preCreatedList的引用,自然你的两个同类型属性会指向同一个列表。

正确的做法应该是把对象创建逻辑放在委托内部,确保每次请求都生成新实例:

// 正确:每次请求都创建新的列表
fixture.Register(() => new List<string>());

2. 使用CreateMany<string>(3).ToList()导致的失败

这个场景的问题本质和上面类似——很多人会犯的错误是:提前执行ToList()并把结果缓存起来,然后注册成返回这个缓存的实例。比如:

// 错误:只生成一次带3个元素的列表,所有请求复用它
var fixedLengthList = fixture.CreateMany<string>(3).ToList();
fixture.Register(() => fixedLengthList);

哪怕你用了CreateMany,只要是提前生成好列表再返回,结果还是同一个引用。

正确的写法是让委托每次都重新执行CreateMany和ToList:

// 正确:每次请求都生成新的、带3个元素的列表
fixture.Register(() => fixture.CreateMany<string>(3).ToList());

另外提一句,AutoFixture 4.0对集合的生成策略做了调整,相比3.50.7会更严格地检查实例复用的场景,所以同样的错误在4.0中更容易暴露出来。

3. 额外的排查建议

如果你不确定问题出在哪,可以在测试中打印两个属性的GetHashCode()或者直接比较引用:

var sut = fixture.Create<YourClass>();
Console.WriteLine(sut.List1.GetHashCode());
Console.WriteLine(sut.List2.GetHashCode());
Console.WriteLine(ReferenceEquals(sut.List1, sut.List2)); // 正常应该是false

如果输出True,那肯定是实例复用的问题,回头检查你的自定义注册逻辑就行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:55:40