AutoFixture在复杂对象中创建不需要的深度

时间:2015-07-01 21:01:45

标签: c# entity-framework-6 autofixture

我有一个复杂的图表,从EF6(数据库优先),我想在测试我的域模型时使用模拟和测试夹具进行模拟。为了防止循环依赖的问题,我将这些行添加到测试设置中:

sessions

然后我尝试阻止灯具试图将对象图追逐到遗忘状态,并且只创建一个没有任何子节点的简单对象,如下所示:

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));

这样就不会创建属于此EntityType属性的对象或集合。其余属性是简单类型,包括一些Nullable和DateTime值以及Int32和String类型。

我想让AutoFixture创建一个EntityType实例,然后我打算从模拟中返回它。 (这可能不相关。)

        _fixture.Build<EntityType>()
            .Without(e => e.ObjectProperty1)
            .Without(e => e.ObjectProperty2)
            .Without(e => e.CollectionProperty3)
            .Without(e => e.CollectionProperty4)
            .Without(e => e.ObjectProperty5)
            ...
            .Create();

然后我将对象添加到这个模拟中:

        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访问的所有可能对象。我怎么知道?因为我开启了追踪。仅针对这一个Create操作,将生成近750,000行跟踪(它是100MB文件)。

在阅读跟踪时,第一部分显示了EntityType的创建以及我未排除的所有属性的设置。但是在那件东西被创建之后,它似乎再次被创建,但这次它忽略了我的.Without()自定义,并且深入。

Without()

就在那里,我希望跟踪完成。对象被创建,正是我想要的。但它并不止于此。紧接着,我看到AutoFixture继续前进。

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

当然,这些东西可能有各种代码味道,我知道Mark Seemann在EF或任何其他ORM上并不大。但我认为它应该有效,我无法弄清楚我错过了什么。

2 个答案:

答案 0 :(得分:1)

现在我更仔细地看一下这些例子,以回答Mark的评论(谢谢你,Mark !! )......我发现Build的类型为T的返回值方法。 (打击前额)

所以现在我发现我认为Build的确错了。它实际上在那里实例化了一个T.我怀疑我需要做什么(创建模板)是扩展SpecimenBuilder并通过在设置Fixture的Customize / Customizations序列中添加它来以某种方式注册。

马克,如果你想留下更好的答案,我会等一两天,然后选择你的答案作为正确答案。

答案 1 :(得分:0)

尝试使用RepeatCount属性

var objFixture =新的Fixture();

objFixture.RepeatCount = 0;