與許多有關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#或哈斯克爾.. 。
然而,讓我們假設,我們有預定義的街道名稱的列表:
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
。只需將其添加到您的測試代碼庫而不是生產代碼庫。
是的,這是可能的:http://blog.ploeh.dk/2010/11/22/IntegratingAutoFixturewithObjectHydrator –