[英]Can AutoFixture generate random strings/text from a provided data set?
It is possible to use AutoFixture to generate random data for a string property .. but it's from a fixed data source? 可以使用AutoFixture为字符串属性生成随机数据..但是它来自固定数据源?
For example: I have 30 street names hardcoded into a memory collection (array/list/whatever). 例如:我有30个街道名称被硬编码到一个内存集合中(数组/列表/其他)。 Then, for my Address
instance, the StreetName
property isn't just a random string value (which is the default result from AutoFixture) but one of the street names from that hardcoded collection. 然后,对于我的Address
实例, StreetName
属性不仅是一个随机字符串值(这是AutoFixture的默认结果),而且是该硬编码集合中的街道名称之一。
My first thought was to use a random number which AutoFixture might be able to create.. and this number is inside the array length/size ... so in effect i'm randomizing an array slot. 我的第一个想法是使用一个可以由AutoFixture创建的随机数..而这个数字在数组的长度/大小之内...因此,实际上我正在将数组插槽随机化。 Then, using this random number, get the value (aka street name) of the collection/array slot (ie. given the indexer, get the value at that index location). 然后,使用该随机数,获取集合/阵列插槽的值(即街道名称)(即,给定索引器,获取该索引位置的值)。
Is this how it should be done? 这是应该怎么做?
As with so many other things regarding AutoFixture, things become much easier if you can use more explicit domain modelling . 与其他有关AutoFixture的事情一样,如果您可以使用更明确的域建模 ,则事情会变得容易得多。 Instead of modelling StreetName
as a string
, introduce a domain object for it: 不要将StreetName
建模为string
,而是StreetName
引入域对象:
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);
}
}
This is one of those modelling steps that are painful in C# and Java, but would be a one-liner in F# or Haskell... 这是在C#和Java中痛苦的建模步骤之一,但在F#或Haskell中却是一线的。
Let's assume, however, that we have a list of predefined street names: 但是,让我们假设我们有一个预定义的街道名称列表:
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... */ };
}
You can now trivially tell AutoFixture to pick only from that list, using ElementsBuilder
: 现在,您可以使用ElementsBuilder
轻松地告诉AutoFixture仅从该列表中进行选择:
var fixture = new Fixture();
fixture.Customizations.Add(
new ElementsBuilder<StreetName>(StreetNames.Values.Select(s => (StreetName)s)));
At this point, though, it means that when you create StreetName
values with AutoFixture, it'll pick from StreetNames.Values
, but it still isn't going to do that when you ask it to create Address
values. 不过,这意味着,当您使用StreetName
创建StreetName
值时,它将从StreetNames.Values
,但是当您要求它创建Address
值时,它仍然不会这样做。 You can address (ha ha) that issue with a little ISpecimenBuilder
: 您可以使用一个小的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;
}
}
Now you can configure your Fixture
like this: 现在您可以像这样配置您的Fixture
:
var fixture = new Fixture();
fixture.Customizations.Add(
new ElementsBuilder<StreetName>(StreetNames.Values.Select(s => (StreetName)s)));
fixture.Customizations.Add(new StreetNameBuilder());
It'll now create Address
values with StreetName
values picked from the predefined list. 现在, StreetName
从预定义列表中选取的StreetName
值来创建Address
值。
If you can't change your domain model, you can still add a class like StreetName
. 如果您无法更改域模型,则仍可以添加StreetName
类的类。 Just add it to your test code base instead of the production code base. 只需将其添加到测试代码库而不是生产代码库即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.