2016-02-08 21 views
1

可以使用AutoFixture爲字符串屬性生成隨機數據..但它來自固定的數據源?AutoFixture是否可以從提供的數據集中生成隨機字符串/文本?

例如:我有30個街道名稱硬編碼到內存集合(數組/列表/任何)。然後,對於我的Address實例,StreetName屬性不僅是隨機字符串值(這是AutoFixture的默認結果),而是該硬編碼集合中的街道名稱之一。

我的第一個想法是使用AutoFixture可能能夠創建的一個隨機數,並且這個數字在數組長度/大小內......所以實際上我隨機化了一個數組槽。然後,使用這個隨機數,得到集合/數組槽的值(又名街道名稱)(即給定索引器,獲取該索引位置的值)。

這是應該怎麼做?

+2

是的,這是可能的:http://blog.ploeh.dk/2010/11/22/IntegratingAutoFixturewithObjectHydrator –

回答

0

與許多有關AutoFixture的其他內容一樣,如果您可以使用use more explicit domain modelling,事情會變得更加容易。相反建模StreetNamestring的,引入域對象吧:

public sealed class StreetName 
{ 
    private readonly string value; 

    public StreetName(string streetName) 
    { 
     value = streetName ?? throw new ArgumentNullException(nameof(streetName)); 
    } 

    public override bool Equals(object obj) 
    { 
     var other = obj as StreetName; 
     if (other == null) 
      return base.Equals(obj); 

     return Equals(value, other.value); 
    } 

    public override int GetHashCode() 
    { 
     return value.GetHashCode(); 
    } 

    public override string ToString() 
    { 
     return value; 
    } 

    public static implicit operator string(StreetName streetAddress) 
    { 
     return streetAddress.value; 
    } 

    public static implicit operator StreetName(string streetAddress) 
    { 
     return new StreetName(streetAddress); 
    } 
} 

這是那些在C#和Java痛苦的造型步驟之一,但將是一個班輪在F#或哈斯克爾.. 。

然而,讓我們假設,我們有預定義的街道名稱的列表:

public static class StreetNames 
{ 
    public static IEnumerable<string> Values = new[] { 
     "221 B Baker St.", 
     "1313 Webfoot Walk", 
     "420 Paper St.", 
     "42 Wallaby Way" 
     /* More addresses go here... */ }; 
} 

現在你可以平凡告訴AutoFixture只從列表中選擇,使用ElementsBuilder

var fixture = new Fixture(); 
fixture.Customizations.Add(
    new ElementsBuilder<StreetName>(StreetNames.Values.Select(s => (StreetName)s))); 

在這一點上,雖然,這意味着當你創建AutoFixture StreetName值,它會從StreetNames.Values回暖,但它仍然是不打算這樣做,當你問它來創建Address值。你可以解決(哈哈)這個問題有一點ISpecimenBuilder

public class StreetNameBuilder : ISpecimenBuilder 
{ 
    public object Create(object request, ISpecimenContext context) 
    { 
     var pi = request as PropertyInfo; 
     if (pi == null || pi.Name != "StreetName" || pi.PropertyType != typeof(string)) 
      return new NoSpecimen(); 

     var sn = context.Resolve(typeof(StreetName)); 
     return (string)(StreetName)sn; 
    } 
} 

現在,你可以配置你Fixture這樣的:

var fixture = new Fixture(); 
fixture.Customizations.Add(
    new ElementsBuilder<StreetName>(StreetNames.Values.Select(s => (StreetName)s))); 
fixture.Customizations.Add(new StreetNameBuilder()); 

現在將創建Address值與StreetName值從採摘預定義列表。

如果你不能改變你的域模型,你仍然可以添加一個類如StreetName。只需將其添加到您的測試代碼庫而不是生產代碼庫。