第一季度
为了定位(或者更确切地说,省略)在基类上定义的属性,我知道没有比定义自定义 ISpecimenBuilder 更好的方法了,在这种情况下类似于:
public class OmitLanguageBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var pi = request as PropertyInfo;
if (pi != null &&
pi.PropertyType == typeof(Language)
&& pi.Name == "Language"
&& pi.DeclaringType == typeof(BaseItem))
return new OmitSpecimen();
return new NoSpecimen();
}
}
这专门处理仅在BaseItem 上声明的Language 属性的请求。如果您想不那么具体,您可以删除if 表达式中的一些谓词。当 AutoFixture 收到这样的请求时,它会将特殊的“信号类型”OmitSpecimen 解释为忽略该属性的指令。
您可以直接将OmitLanguageBuilder 注册到Fixture 实例(尽管您应该将其打包在自定义中。此测试通过:
[Fact]
public void Q1A()
{
var fixture = new Fixture();
fixture.Customizations.Add(new OmitLanguageBuilder());
var actual = fixture.Create<ItemA>();
Assert.Null(actual.Language);
Assert.NotEqual(default(Guid), actual.Id);
Assert.NotNull(actual.Name);
}
ItemB 的类似测试也通过了。
第二季度
当您想在特殊测试用例中填充 Language 时,最简单的解决方案可能就是在事后填充它:
[Fact]
public void Q2SetAfter()
{
var fixture = new Fixture();
fixture.Customizations.Add(new OmitLanguageBuilder());
var actual = fixture.Create<ItemA>();
actual.Language = fixture.Create<Language>();
Assert.NotNull(actual.Language);
Assert.NotEqual(default(Guid), actual.Id);
Assert.NotNull(actual.Name);
}
另一种选择是使用Build API:
[Fact]
public void Q2Build()
{
var fixture = new Fixture();
fixture.Customizations.Add(new OmitLanguageBuilder());
var actual =
fixture.Build<ItemA>().With(x => x.Language, fixture.Create<Language>()).Create();
Assert.NotNull(actual.Language);
Assert.NotEqual(default(Guid), actual.Id);
Assert.NotNull(actual.Name);
}
最后,如果您需要更改 AutoFixture 处理类型的一般方式,您可以执行以下操作:
[Fact]
public void Q2Customize()
{
var fixture = new Fixture();
fixture.Customizations.Add(new OmitLanguageBuilder());
fixture.Customize<ItemA>(c => c.With(x => x.Language, fixture.Create<Language>()));
var actual = fixture.Create<ItemA>();
Assert.NotNull(actual.Language);
Assert.NotEqual(default(Guid), actual.Id);
Assert.NotNull(actual.Name);
}