2016-02-08 2 views
1

Можно использовать AutoFixture для генерации случайных данных для свойства string .. но это из фиксированного источника данных?Может ли AutoFixture генерировать случайные строки/текст из предоставленного набора данных?

Например: у меня есть 30 названий улиц, жестко закодированных в коллекцию памяти (массив/список/безотносительно). Затем для моего экземпляра Address свойство StreetName представляет собой не просто случайное строковое значение (которое является результатом по умолчанию для AutoFixture), но и одним из названий улиц из этой жесткой коллекции.

Моя первая мысль состояла в том, чтобы использовать случайное число, которое может создать AutoFixture .., и это число находится внутри длины массива/размера ... так что в действительности я рандомизирую слот массива. Затем, используя это случайное число, получите значение (ака имя улицы) в слоте коллекции/массива (т. Е. С учетом индексатора, получите значение в этом месте индекса).

Это как это сделать?

+2

Да, это возможно: http://blog.ploeh.dk/2010/11/22/IntegratingAutoFixturewithObjectHydrator –

ответ

0

Как и многие другие вещи, связанные с AutoFixture, все становится намного проще, если вы можете use more explicit domain modelling. Вместо моделирования StreetName как string, ввести объект домена для него:

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 # или Haskell .. .

предположим, однако, что у нас есть список предопределенных названий улиц:

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

На данный момент, хотя, это означает, что при создании StreetName значения с AutoFixture, он будет выбирать из 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. Просто добавьте его в базу тестового кода вместо базы производственного кода.

Смежные вопросы