Установка значения свойства для дочернего экземпляра на фиксированное значение с помощью Autofixture
Можно ли назначить фиксированное значение для свойства дочернего экземпляра при создании родителя с помощью Autofixture? Он добавит значения по умолчанию ко всем свойствам дочернего экземпляра, как шарм, но я хотел бы переопределить и присвоить определенное значение одному из свойств дочернего экземпляра.
Учитывая это отношение родитель/ребенок:
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<Person>()
.With(x => x.Address.City, expectedCity)
.Create();
Assert.AreEqual(expectedCity, person.Address.City);
Это невозможно. Я думаю, по исключению отражения
System.Reflection.TargetException : Object does not match target type.
... что Autofixture пытается присвоить значение атрибуту City в экземпляре Person вместо экземпляра Address.
Любые предложения?
И да, я знаю, что я мог бы просто добавить дополнительный шаг, как показано ниже:
var fixture = new Fixture();
var expectedCity = "foo";
// extra step begin
var address = fixture
.Build<Address>()
.With(x => x.City, expectedCity)
.Create();
// extra step end
var person = fixture
.Build<Person>()
.With(x => x.Address, address)
.Create();
Assert.AreEqual(expectedCity, person.Address.City);
... но надеялся на первую версию или что-то подобное (меньше шагов, более краток).
Примечание. Я использую Autofixture v3.22.0
Ответы
Ответ 1
Не следует игнорировать вопрос, но самым простым решением могло бы быть следующее:
[Fact]
public void SimplestThingThatCouldPossiblyWork()
{
var fixture = new Fixture();
var expectedCity = "foo";
var person = fixture.Create<Person>();
person.Address.City = expectedCity;
Assert.Equal(expectedCity, person.Address.City);
}
Назначение явных значений свойствам - это то, что большинство языков уже превосходит (возможно, С#), поэтому я не думаю, что AutoFixture нуждается в сложном DSL для воспроизведения половины этой функции.
Ответ 2
Для полноты, здесь другой способ сделать это:
fixture.Customize<Address>(c =>
c.With(addr => addr.City, "foo"));
var person = fixture.Create<Person>();
Это позволит настроить создание всех экземпляров Address
Если вы в конечном итоге используете это достаточно часто, может быть полезно обернуть его внутри ICustomization
:
public class AddressConventions : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<Address>(c =>
c.With(addr => addr.City, "foo"));
}
}
fixture.Customize(new AddressConventions());
Ответ 3
Вы можете использовать метод Do в построителе:
var person = this.fixture
.Build<Person>()
.Do( x => x.Address.City = expectedCity )
.Create();
Вы также можете ввести и заморозить свой экземпляр на прибор:
this.fixture.Inject( expectedCity );