2016-07-31 68 views
4

我想使用自動混合來創建一個對象,但他們是某些屬性,我想總是默認(而其餘的可以自動生成)。但是,每當我設置自定義時,它會在我使用自定義創建時被覆蓋。如何使用AutoFixture在保留類型自定義的同時使用自定義屬性進行構建?

void Main() 
{ 
    var fixture = new Fixture(); 
    fixture.Customize<Person>(composer => composer.With(p => p.Name, "Ben")); 

    var person = fixture.Build<Person>() 
     .With(p => p.DateOfBirth, new DateTime(1900, 1, 1)) 
     .Create(); 

    /* RESULT OF person below 
    Name null 
    DateOfBirth 1/1/1900 
    StreetAddress StreetAddressafd6b86b-376a-4355-9a9c-fbae34731453 
    State State019e867b-ac5e-418f-805b-a64146bc06bc 
    */ 
} 

public class Person 
{ 
    public string Name { get; set;} 

    public DateTime DateOfBirth { get; set;} 

    public string StreetAddress { get; set;} 

    public string State { get; set;} 
} 

「Name」和「DateOfBirth」屬性自定義不衝突,所以我不知道爲什麼Name最終爲null。我希望名字是「本」。 ?

我怎樣才能得到它這樣既定製應用(即名稱=「奔」和出生日期= 1/1/1900

回答

6

正如@DavidOsborne正確指出的那樣,您看到的行爲是as designed

A better approach將在不同的類中組織您的自定義,然後根據特定測試場景的需要啓用它們。

自定義對象實現了ICustomization接口,其作業是以特定方式配置Fixture對象。這裏有一個例子:

public class AllPersonsAreNamedBen : ICustomization 
{ 
    public void Customize(IFixture fixture) 
    { 
     fixture.Customize<Person>(composer => 
      composer.With(p => p.Name, "Ben")); 
    } 
} 

public class AllPersonsAreBornIn1900 : ICustomization 
{ 
    public void Customize(IFixture fixture) 
    { 
     fixture.Customize<Person>(composer => 
      composer.With(p => p.DateOfBirth, new DateTime(1900, 1, 1))); 
    } 
} 

您可以通過使用Customize方法能夠在特定Fixture定製,例如:

fixture.Customize(new AllPersonsAreNamedBen()); 

或:

fixture.Customize(new AllPersonsAreBornIn1900()); 

您還可以結合多個通過使用CompositeCustomization類別將其定製爲新的:

public class AllPersonsAreNamedBenAndAreBornIn1900 : CompositeCustomization 
{ 
    public AllPersonsAreNamedBenAndAreBornIn1900() 
     : base(new AllPersonsAreNamedBen(), 
       new AllPersonsAreBornIn1900()) 
    { 
    } 
} 

此時您可以簡單地說:

fixture.Customize(new AllPersonsAreNamedBenAndAreBornIn1900()); 

但是,請記住,在這些自定義設置在Fixture事項應用順序:最後1個勝場,並有可能覆蓋的正如@MarkSeemann在評論中指出的那樣。這也是by design

所以,雖然你可以結合現有上不同類型的工作,在這種特殊情況下的自定義,因爲這兩個自定義的目標相同類型的,你必須創建一個新的自定義封裝所有的設置在Person型組合:

public class AllPersonsAreNamedBenAndAreBornIn1900 : CompositeCustomization 
{ 
    public void Customize(IFixture fixture) 
    { 
     fixture.Customize<Person>(composer => 
      composer.With(p => p.Name, "Ben") 
        .With(p => p.DateOfBirth, new DateTime(1900, 1, 1))); 
    } 
} 

作爲一般規則,讓您的自定義小集中使您能夠在reuse them不同的測試,他們結合具體的測試場景。

+1

「AllPersonsAreNamedBen」是否將[重寫](http://blog.ploeh.dk/2012/07/31/TheorderofAutoFixtureCustomizationsmatter)'AllPersonsAreBornIn1900'? –

+0

我站好了。由於這兩個定製工作在相同的類型,他們絕對會。感謝您的呼喚!這是AutoFixture的一個方面,時不時地咬我 - 我希望我可以像增量那樣組合多個自定義,所以*壞*,我有時會忘記它是不可能的。 –

+0

我更新了我的答案以糾正錯誤。 –

6

這看起來像它的設計:

注意構建方法鏈最好理解爲一次性定製,它繞過Fixture實例上的所有定製,而是在構建特定樣本時允許進行細粒度控制,但在大多數情況下,添加基於約定的ICustomization更好,更靈活的選擇。

...來自Build()方法的文檔。

我明白這可能不是一個理想的答案。但是,文檔確實提供了有關如何到達其中的提示。

相關問題