AutoFixture 在复杂对象中创建不需要的深度
AutoFixture creating unwanted depth in complex objects
我有一个来自 EF6(数据库优先)的复杂图形,我想在测试我的域模型时使用模拟和测试装置进行模拟。为了防止循环依赖问题,我将这些行添加到测试设置中:
private Fixture _fixture;
public WhenRetrievingPlans()
{
_fixture = new Fixture();
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
using (var writer = new StreamWriter(@"D:\Workspace\Project\source\Project.Model.Test\trace.txt"))
{
_fixture.Behaviors.Add(new TracingBehavior(writer));
然后我试图阻止 fixture 试图将对象图遗忘,然后只创建一个没有任何子对象的简单对象,如下所示:
_fixture.Build<EntityType>()
.Without(e => e.ObjectProperty1)
.Without(e => e.ObjectProperty2)
.Without(e => e.CollectionProperty3)
.Without(e => e.CollectionProperty4)
.Without(e => e.ObjectProperty5)
...
.Create();
因此不会创建作为此 EntityType 属性的对象或集合。其余属性都是简单类型,包括一些 Nullable 和 DateTime 值以及 Int32 和 String 类型。
我想让 AutoFixture 创建 EntityType 的实例,然后我打算 return 从 Mock 中创建它。 (这可能不相关。)
var entitiesDbSetMock = new Mock<IDbSet<EntityType>>();
entitiesDbSetMock.SetupAllProperties();
_fixture.Inject<IDbSet<EntityType>>(entitiesDbSetMock.Object);
然后我将对象添加到这个模拟中:
var entity = _fixture.Create<EntityType>();
entitiesDbSetMock.Object.Attach(entity);
问题是这样的:AutoFixture 并没有阻止自己生成可以从此 EntityType 到达的每个可能的对象,即使我使用了所有 .Without()
操作。我怎么知道?因为我打开了追踪。仅仅为了这个 Create 操作,就生成了将近 750,000 行跟踪(这是一个 100MB 的文件)。
在阅读跟踪时,第一部分显示了 EntityType 的创建和我没有排除的所有属性的设置。但是在那个东西被创建之后,它似乎又被创建了,但是这次它忽略了我的 Without()
定制,并且深入。
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.EntityType
Requested: Int32 EntityTypeID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 232
Created: 232
Created: 232
Requested: System.Nullable`1[System.Int32] ForeignKey1ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Nullable`1[System.Int32]
Requested: Int32 value
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 224
Created: 224
Created: 224
Created: 224
Created: 224
Created: 224
Requested: Int32 Property2ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 40
Created: 40
Created: 40
Requested: System.DateTime Property3Date
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.DateTime
Created: 6/6/2014 4:05:24 PM
Created: 6/6/2014 4:05:24 PM
Created: 6/6/2014 4:05:24 PM
*... (similar lines elided for brevity)*
Requested: Project.Data.OtherEntity OtherEntity
Created: Ploeh.AutoFixture.Kernel.OmitSpecimen
Requested: Project.Data.YetAnotherEntity YetAnotherEntity
Created: Ploeh.AutoFixture.Kernel.OmitSpecimen
Requested: System.Collections.Generic.ICollection`1[Project.Data.CollectionEntity] CollectionEntities
Created: Ploeh.AutoFixture.Kernel.OmitSpecimen
*... (similar lines elided for brevity)*
Created: Project.Data.EntityType
Created: Project.Data.EntityType
就在那儿,我希望跟踪完成。对象被创建,正是我想要的。但它并不止于此。紧随其后,我看到 AutoFixture 继续前进。
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.YetAnotherEntity
Created: Project.Data.YetAnotherEntity
Created: Project.Data.YetAnotherEntity
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.UnrelatedEntity
Created: Project.Data.UnrelatedEntity
Created: Project.Data.UnrelatedEntity
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.EntityType *<<-- Again? We did this already.*
Requested: Int32 EntityTypeID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 107
Created: 107
Created: 107
Requested: System.Nullable`1[System.Int32] ForeignKey1ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Nullable`1[System.Int32]
Requested: Int32 value
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 87
Created: 87
Created: 87
Created: 87
Created: 87
Created: 87
Requested: Int32 Property2ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 105
Created: 105
Created: 105
Requested: System.DateTime Property3Date
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.DateTime
Created: 5/31/2014 6:50:10 PM
Created: 5/31/2014 6:50:10 PM
Created: 5/31/2014 6:50:10 PM
Requested: Project.Data.OtherEntity OtherEntity *<<!! NO! I stopped you!*
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.OtherEntity
Requested: Int32 ForeignKey1ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 168
Created: 168
Created: 168
Requested: System.String Name
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.String
Created: 61eb26e3-890d-4d0d-badd-cd3467c299ed
Created: Name61eb26e3-890d-4d0d-badd-cd3467c299ed
Created: Name61eb26e3-890d-4d0d-badd-cd3467c299ed
Requested: Int32 OtherEntityID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 187
Created: 187
Created: 187
*... and on and on for 750,000 more lines.
当然,这个东西可能有各种代码味道,而且我知道 Mark Seemann 对 EF 或任何其他 ORM 并不感兴趣。但我认为它应该有效,我无法弄清楚我错过了什么。
现在我更仔细地查看示例以回答 Mark 的评论(谢谢你,Mark!!)...我看到有一个 return Build 方法的类型 T 的值。 (拍额头)。
所以现在我发现我认为 Build 的做法是错误的。它实际上在那里实例化了一个 T。我怀疑我需要做的(创建模板)是扩展 SpecimenBuilder 并以某种方式注册它,方法是将其添加到设置 Fixture 的 Customize/Customizations 序列中。
马克,如果你想留下更好的答案,我会等一两天,然后选择你的答案作为正确答案。
尝试使用 RepeatCount 属性
var objFixture = new Fixture();
objFixture.RepeatCount = 0;
我有一个来自 EF6(数据库优先)的复杂图形,我想在测试我的域模型时使用模拟和测试装置进行模拟。为了防止循环依赖问题,我将这些行添加到测试设置中:
private Fixture _fixture;
public WhenRetrievingPlans()
{
_fixture = new Fixture();
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
using (var writer = new StreamWriter(@"D:\Workspace\Project\source\Project.Model.Test\trace.txt"))
{
_fixture.Behaviors.Add(new TracingBehavior(writer));
然后我试图阻止 fixture 试图将对象图遗忘,然后只创建一个没有任何子对象的简单对象,如下所示:
_fixture.Build<EntityType>()
.Without(e => e.ObjectProperty1)
.Without(e => e.ObjectProperty2)
.Without(e => e.CollectionProperty3)
.Without(e => e.CollectionProperty4)
.Without(e => e.ObjectProperty5)
...
.Create();
因此不会创建作为此 EntityType 属性的对象或集合。其余属性都是简单类型,包括一些 Nullable 和 DateTime 值以及 Int32 和 String 类型。
我想让 AutoFixture 创建 EntityType 的实例,然后我打算 return 从 Mock 中创建它。 (这可能不相关。)
var entitiesDbSetMock = new Mock<IDbSet<EntityType>>();
entitiesDbSetMock.SetupAllProperties();
_fixture.Inject<IDbSet<EntityType>>(entitiesDbSetMock.Object);
然后我将对象添加到这个模拟中:
var entity = _fixture.Create<EntityType>();
entitiesDbSetMock.Object.Attach(entity);
问题是这样的:AutoFixture 并没有阻止自己生成可以从此 EntityType 到达的每个可能的对象,即使我使用了所有 .Without()
操作。我怎么知道?因为我打开了追踪。仅仅为了这个 Create 操作,就生成了将近 750,000 行跟踪(这是一个 100MB 的文件)。
在阅读跟踪时,第一部分显示了 EntityType 的创建和我没有排除的所有属性的设置。但是在那个东西被创建之后,它似乎又被创建了,但是这次它忽略了我的 Without()
定制,并且深入。
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.EntityType
Requested: Int32 EntityTypeID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 232
Created: 232
Created: 232
Requested: System.Nullable`1[System.Int32] ForeignKey1ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Nullable`1[System.Int32]
Requested: Int32 value
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 224
Created: 224
Created: 224
Created: 224
Created: 224
Created: 224
Requested: Int32 Property2ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 40
Created: 40
Created: 40
Requested: System.DateTime Property3Date
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.DateTime
Created: 6/6/2014 4:05:24 PM
Created: 6/6/2014 4:05:24 PM
Created: 6/6/2014 4:05:24 PM
*... (similar lines elided for brevity)*
Requested: Project.Data.OtherEntity OtherEntity
Created: Ploeh.AutoFixture.Kernel.OmitSpecimen
Requested: Project.Data.YetAnotherEntity YetAnotherEntity
Created: Ploeh.AutoFixture.Kernel.OmitSpecimen
Requested: System.Collections.Generic.ICollection`1[Project.Data.CollectionEntity] CollectionEntities
Created: Ploeh.AutoFixture.Kernel.OmitSpecimen
*... (similar lines elided for brevity)*
Created: Project.Data.EntityType
Created: Project.Data.EntityType
就在那儿,我希望跟踪完成。对象被创建,正是我想要的。但它并不止于此。紧随其后,我看到 AutoFixture 继续前进。
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.YetAnotherEntity
Created: Project.Data.YetAnotherEntity
Created: Project.Data.YetAnotherEntity
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.UnrelatedEntity
Created: Project.Data.UnrelatedEntity
Created: Project.Data.UnrelatedEntity
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.EntityType *<<-- Again? We did this already.*
Requested: Int32 EntityTypeID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 107
Created: 107
Created: 107
Requested: System.Nullable`1[System.Int32] ForeignKey1ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Nullable`1[System.Int32]
Requested: Int32 value
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 87
Created: 87
Created: 87
Created: 87
Created: 87
Created: 87
Requested: Int32 Property2ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 105
Created: 105
Created: 105
Requested: System.DateTime Property3Date
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.DateTime
Created: 5/31/2014 6:50:10 PM
Created: 5/31/2014 6:50:10 PM
Created: 5/31/2014 6:50:10 PM
Requested: Project.Data.OtherEntity OtherEntity *<<!! NO! I stopped you!*
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: Project.Data.OtherEntity
Requested: Int32 ForeignKey1ID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 168
Created: 168
Created: 168
Requested: System.String Name
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.String
Created: 61eb26e3-890d-4d0d-badd-cd3467c299ed
Created: Name61eb26e3-890d-4d0d-badd-cd3467c299ed
Created: Name61eb26e3-890d-4d0d-badd-cd3467c299ed
Requested: Int32 OtherEntityID
Requested: Ploeh.AutoFixture.Kernel.SeededRequest
Requested: System.Int32
Created: 187
Created: 187
Created: 187
*... and on and on for 750,000 more lines.
当然,这个东西可能有各种代码味道,而且我知道 Mark Seemann 对 EF 或任何其他 ORM 并不感兴趣。但我认为它应该有效,我无法弄清楚我错过了什么。
现在我更仔细地查看示例以回答 Mark 的评论(谢谢你,Mark!!)...我看到有一个 return Build 方法的类型 T 的值。 (拍额头)。
所以现在我发现我认为 Build 的做法是错误的。它实际上在那里实例化了一个 T。我怀疑我需要做的(创建模板)是扩展 SpecimenBuilder 并以某种方式注册它,方法是将其添加到设置 Fixture 的 Customize/Customizations 序列中。
马克,如果你想留下更好的答案,我会等一两天,然后选择你的答案作为正确答案。
尝试使用 RepeatCount 属性
var objFixture = new Fixture();
objFixture.RepeatCount = 0;