对某些类型使用自动混合构建方法时,如何限制生成的字符串的长度以填充对象字符串属性/字段?
Mar*_*ann 50
使用Build
方法本身,没有那么多选项,但你可以做这样的事情:
var constrainedText =
fixture.Create<string>().Substring(0, 10);
var mc = fixture
.Build<MyClass>()
.With(x => x.SomeText, constrainedText)
.Create();
Run Code Online (Sandbox Code Playgroud)
但是,就个人而言,我看不出这是更好或更容易理解的:
var mc = fixture
.Build<MyClass>()
.Without(x => x.SomeText)
.Create();
mc.SomeText =
fixture.Create<string>().Substring(0, 10);
Run Code Online (Sandbox Code Playgroud)
就个人而言,我很少使用这种Build
方法,因为我更喜欢基于约定的方法.这样做,至少有三种方法来约束字符串长度.
第一个选项只是约束所有字符串的基础:
fixture.Customizations.Add(
new StringGenerator(() =>
Guid.NewGuid().ToString().Substring(0, 10)));
var mc = fixture.Create<MyClass>();
Run Code Online (Sandbox Code Playgroud)
上面的自定义将所有生成的字符串截断为10个字符.但是,由于默认属性赋值算法会将属性的名称添加到字符串中,因此最终结果mc.SomeText
将具有类似"SomeText3c12f144-5"的值,因此这可能不是您想要的大多数时间.
另一个选择是使用该[StringLength]
属性,正如Nikos所指出的:
public class MyClass
{
[StringLength(10)]
public string SomeText { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这意味着您只需创建一个实例,而无需明确说明属性的长度:
var mc = fixture.Create<MyClass>();
Run Code Online (Sandbox Code Playgroud)
我能想到的第三个选择是我最喜欢的.这添加了一个特定的目标约定,该约定规定每当要求fixture为名称为"SomeText"且类型为string的属性创建值时,结果字符串应为10个字符长:
public class SomeTextBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var pi = request as PropertyInfo;
if (pi != null &&
pi.Name == "SomeText" &&
pi.PropertyType == typeof(string))
return context.Resolve(typeof(string))
.ToString().Substring(0, 10);
return new NoSpecimen();
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
fixture.Customizations.Add(new SomeTextBuilder());
var mc = fixture.Create<MyClass>();
Run Code Online (Sandbox Code Playgroud)
这种方法的优点在于它只留下SUT并且仍然不会影响任何其他字符串值.
您可以将其概括SpecimenBuilder
为任何类和长度,如下所示:
public class StringPropertyTruncateSpecimenBuilder<TEntity> : ISpecimenBuilder
{
private readonly int _length;
private readonly PropertyInfo _prop;
public StringPropertyTruncateSpecimenBuilder(Expression<Func<TEntity, string>> getter, int length)
{
_length = length;
_prop = (PropertyInfo)((MemberExpression)getter.Body).Member;
}
public object Create(object request, ISpecimenContext context)
{
var pi = request as PropertyInfo;
return pi != null && AreEquivalent(pi, _prop)
? context.Create<string>().Substring(0, _length)
: (object) new NoSpecimen(request);
}
private bool AreEquivalent(PropertyInfo a, PropertyInfo b)
{
return a.DeclaringType == b.DeclaringType
&& a.Name == b.Name;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
fixture.Customizations.Add(
new StringPropertyTruncateSpecimenBuilder<Person>(p => p.Initials, 5));
Run Code Online (Sandbox Code Playgroud)
Nik*_*nis 12
如果最大长度是约束并且您拥有该类型的源代码,则可以使用StringLengthAttribute类指定允许的最大字符长度.
从版本2.6.0开始,AutoFixture支持DataAnnotations,它将自动生成指定最大长度的字符串.
举个例子,
public class StringLengthValidatedType
{
public const int MaximumLength = 3;
[StringLength(MaximumLength)]
public string Property { get; set; }
}
[Fact]
public void CreateAnonymousWithStringLengthValidatedTypeReturnsCorrectResult()
{
// Fixture setup
var fixture = new Fixture();
// Exercise system
var result = fixture.CreateAnonymous<StringLengthValidatedType>();
// Verify outcome
Assert.True(result.Property.Length <= StringLengthValidatedType.MaximumLength);
// Teardown
}
Run Code Online (Sandbox Code Playgroud)
使用Build时(以自定义单个对象的创建算法),上述测试也将通过:
var result = fixture.Build<StringLengthValidatedType>().CreateAnonymous();
Run Code Online (Sandbox Code Playgroud)
小智 7
这是我的解决方案。当字符串包含什么并不重要时,我使用这种方法:
public static string GetStringOfLength(this IFixture fixture, int length)
{
return string.Join("", fixture.CreateMany<char>(length));
}
Run Code Online (Sandbox Code Playgroud)
它很短而且对我有用。
归档时间: |
|
查看次数: |
13929 次 |
最近记录: |