2015-11-10 46 views
5

鑑於兩類:定製AutoFixure使用FromSeed導致異常

class Foo 
{ 
    ... 
} 

class Bar 
{ 
    public Foo FooBar { get; set; } 
} 

我已經設置了以下測試:

void Test() 
{ 
    var fixture = new Fixture(); 

    fixture.Customize<Foo>(x => x.FromSeed(TestFooFactory)); 

    var fooWithoutSeed = fixture.Create<Foo>(); 
    var fooWithSeed = fixture.Create<Foo>(new Foo()); 

    var bar = fixture.Create<Bar>(); //error occurs here 
} 

Foo TestFooFactory(Foo seed) 
{ 
    //do something with seed... 

    return new Foo(); 
} 

我能有和沒有種子值創造直接Foo對象沒有任何問題。但是,一旦我嘗試創建一個具有Foo屬性Bar對象,我得到一個ObjectCreationException

裝飾ISpecimenBuilder無法創建基於請求的樣本:富。如果請求表示接口或抽象類,則可能發生這種情況;如果是這種情況,請註冊一個可以根據請求創建標本的ISpecimenBuilder。如果這發生在強類型的Build表達式中,請嘗試使用IFactoryComposer方法之一提供工廠。

我期望TestFooFactory獲得通過創造Bar期間null種子值,就像當我創建Foo沒有種子值。我做錯了什麼,或者這可能是一個錯誤?

在我的實際場景中,我想定製AutoFixture如何在將種子值傳遞給某些對象時使用種子值,但如果未提供種子,我仍然希望AutoFixture默認爲正常行爲。

+3

交叉傳遞給GitHub:https://github.com/AutoFixture/AutoFixture/issues/467 –

回答

5

您自定義Fixture以使用種子值is correct的方式。

您看到的行爲是自定義修改AutoFixture管道的結果。如果你有興趣閱讀細節,我已經描述了他們here

作爲一種變通方法,您可以使用自定義樣本建設者接種的這樣請求:

public class RelaxedSeededFactory<T> : ISpecimenBuilder 
{ 
    private readonly Func<T, T> create; 

    public RelaxedSeededFactory(Func<T, T> factory) 
    { 
     this.create = factory; 
    } 

    public object Create(object request, ISpecimenContext context) 
    { 
     if (request != null && request.Equals(typeof(T))) 
     { 
      return this.create(default(T)); 
     } 

     var seededRequest = request as SeededRequest; 

     if (seededRequest == null) 
     { 
      return new NoSpecimen(request); 
     } 

     if (!seededRequest.Request.Equals(typeof(T))) 
     { 
      return new NoSpecimen(request); 
     } 

     if ((seededRequest.Seed != null) 
      && !(seededRequest.Seed is T)) 
     { 
      return new NoSpecimen(request); 
     } 

     var seed = (T)seededRequest.Seed; 

     return this.create(seed); 
    } 
} 

然後,您可以使用它來創建Foo類型的對象是這樣的:

fixture.Customize<Foo>(c => c.FromFactory(
    new RelaxedSeededFactory<Foo>(TestFooFactory))); 

此定製將在填充Foo類型的屬性時將default(Foo) - 即null - 作爲種子傳遞給TestFooFactory工廠函數。

+0

這就像一個魅力!感謝您的解決方法。 –

+2

我用_better_方法更新了自定義的'RelaxedSeededFactory'標本生成器。它不會處理所有的請求,它只會處理種子和非種子請求'T'。 –

+1

就像更新一樣,AutoFixture 3.36.12修復了這個問題:https://github.com/AutoFixture/AutoFixture/commit/c7ce7d239a26fd7aef8c464ba214c366681d0886。謝謝@Enrico! –