使用Autofixture将子实例上的属性值设置为固定值

在使用Autofixture构建父级时,是否可以为子实例上的属性分配固定值? 它会将默认值添加到子实例上的所有属性(如charm),但我想覆盖并为子实例上的某个属性指定特定值。

鉴于这种父/子关系:

public class Person { public string FirstName { get; set; } public string LastName { get; set; } public Address Address { get; set; } } public class Address { public string Street { get; set; } public int Number { get; set; } public string City { get; set; } public string PostalCode { get; set; } } 

我想在地址实例上为City属性分配一个特定值。 我正在考虑这个测试代码:

 var fixture = new Fixture(); var expectedCity = "foo"; var person = fixture .Build() .With(x => x.Address.City, expectedCity) .Create(); Assert.AreEqual(expectedCity, person.Address.City); 

这是不可能的。 我想,由reflectionexception

 System.Reflection.TargetException : Object does not match target type. 

… Autofixture尝试将值分配给Person实例上的City属性而不是Address实例。

有什么建议?

是的,我知道我可以添加一个额外的步骤,如下所示:

 var fixture = new Fixture(); var expectedCity = "foo"; // extra step begin var address = fixture .Build
() .With(x => x.City, expectedCity) .Create(); // extra step end var person = fixture .Build() .With(x => x.Address, address) .Create(); Assert.AreEqual(expectedCity, person.Address.City);

…但希望第一个版本或类似的东西(更少的步骤,更简洁)。

注意:我使用的是Autofixture v3.22.0

不要轻视这个问题,但最简单的解决方案实际上可能就是这样:

 [Fact] public void SimplestThingThatCouldPossiblyWork() { var fixture = new Fixture(); var expectedCity = "foo"; var person = fixture.Create(); person.Address.City = expectedCity; Assert.Equal(expectedCity, person.Address.City); } 

为属性分配显式值是大多数语言已经擅长的(C#当然可以),所以我不认为AutoFixture需要复杂的DSL来重现一半的function。

为了完整起见,这是另一种方法:

 fixture.Customize
(c => c.With(addr => addr.City, "foo")); var person = fixture.Create();

这将自定义所有Address实例的创建

如果你最终经常使用它,可能值得将它包装在ICustomization

 public class AddressConventions : ICustomization { public void Customize(IFixture fixture) { fixture.Customize
(c => c.With(addr => addr.City, "foo")); } } fixture.Customize(new AddressConventions());

您可以在构建器上使用Do方法:

 var person = this.fixture .Build() .Do( x => x.Address.City = expectedCity ) .Create(); 

您还可以将实例注入并冻结到夹具:

 this.fixture.Inject( expectedCity );