Ответ 1
Ваша первоначальная попытка выглядит хорошо, но есть, по крайней мере, несколько вещей, которые вы можете немного упростить.
Прежде всего, вы должны уменьшить это:
fixture.Register<Location, Location, DateTime, DateTime, CarrierMovement>(
(departure, arrival, departureTime, arrivalTime) =>
new CarrierMovement(departureLoc, arrivalLoc, departureDateTime, arrivalDateTime));
:
fixture.Register<Location, Location, DateTime, DateTime, CarrierMovement>(
() => new CarrierMovement(departureLoc, arrivalLoc, departureDateTime, arrivalDateTime));
так как вы не используете эти другие переменные. Однако это существенно блокирует любое создание CarrierMovement для использования тех же четырех значений. Хотя каждый созданный CarrierMovement будет отдельным экземпляром, все они будут иметь одни и те же четыре значения, и я думаю, что это было то, что вы имели в виду?
В том же духе, что и выше, вместо
fixture.Register<List<CarrierMovement>, Schedule>((carrierM) =>
new Schedule(carrierMovements));
вы можете написать
fixture.Register(() => new Schedule(carrierMovements));
так как вы не используете переменную carrierM
. Тип inferencing будет определять, что вы регистрируете расписание из-за возвращаемого типа Func.
Однако, предполагая, что конструктор Schedule выглядит следующим образом:
public Schedule(IEnumerable<CarrierMovement> carrierMovements)
вы могли бы просто зарегистрировать carrierMovements
следующим образом:
fixture.Register<IEnumerable<CarrierMovement>>(carrierMovements);
из-за чего AutoFixture автоматически разрешит расписание. Этот подход более удобен в обслуживании, поскольку он позволяет добавлять параметр в конструктор Schedule в будущем без нарушения теста (пока AutoFixture может разрешить тип параметра).
Однако в этом случае мы можем сделать лучше, потому что мы действительно не используем переменную carrierMovements
для чего-либо еще, кроме регистрации. Нам действительно нужно просто сказать AutoFixture, как создавать экземпляры IEnumerable<CarrierMovement>
. Если вам не нравится номер 50 (вы не должны), мы можем даже использовать синтаксис группы методов следующим образом:
fixture.Register(fixture.CreateMany<CarrierMovement>);
Обратите внимание на отсутствие паратетов вызова метода: мы регистрируем Func, а так как метод CreateMany<T>
возвращает IEnumerable<T>
, то метод ввода выводит остальные.
Однако все это детали. На более высоком уровне вы можете вообще не учитывать регистрацию CarrierMovement. Предположим, что этот конструктор:
public CarrierMovement(Location departureLocation,
Location arrivalLocation,
DateTime departureTime,
DateTime arrivalTime)
автообъект должен уметь самостоятельно разобраться.
Он создаст новый экземпляр местоположения для каждого location location location и arrivalLocation, но не отличается от того, что вы вручную сделали в оригинальном тесте.
Когда дело доходит до времени, по умолчанию AutoFixture использует DateTime.Now
, что, по крайней мере, гарантирует, что время прибытия никогда не будет до времени отправления. Тем не менее, они, скорее всего, будут идентичными, но вы всегда можете зарегистрировать функцию автоинкремента, если это проблема.
Учитывая эти соображения, здесь альтернатива:
public void should_create_instance_with_correct_ctor_parameters_AutoFixture()
{
var fixture = new Fixture();
fixture.Register(() => new UnLocode(UnLocodeString()));
fixture.Register(fixture.CreateMany<CarrierMovement>);
var schedule = fixture.CreateAnonymous<Schedule>();
schedule.ShouldNotBeNull();
}
Чтобы решить проблему с помощью IList<CarrierMovement>
, вам необходимо ее зарегистрировать. Вот один из способов сделать это:
fixture.Register<IList<CarrierMovement>>(() =>
fixture.CreateMany<CarrierMovement>().ToList());
Однако, поскольку вы спрашиваете, я подразумеваю, что конструктор Schedule выглядит следующим образом:
public Schedule(IList<CarrierMovement> carrierMovements)
и я действительно думаю, что вы должны пересмотреть этот API, чтобы принять IEnumerable<Carriemovement>
. С точки зрения дизайна API, предоставление коллекции через любой член (включая конструктор) подразумевает, что члену разрешено изменять коллекцию (например, путем вызова методов "Добавить", "Удалить" и "Очистить" ). Это вряд ли поведение, которое вы ожидаете от конструктора, поэтому не допускайте его.
AutoFixture автоматически генерирует новые значения для всех объектов Location
в моем примере выше, но из-за скорости процессора последующие экземпляры DateTime, вероятно, будут идентичными.
Если вы хотите увеличить DateTimes, вы можете написать небольшой класс, который увеличивает каждый возвращаемый DateTime каждый раз при его вызове. Я оставлю реализацию этого класса заинтересованному читателю, но вы могли бы зарегистрировать его так:
var dtg = new DateTimeGenerator();
fixture.Register(dtg.Next);
предполагая этот API (еще раз обратите внимание на синтаксис группы методов выше):
public class DateTimeGenerator
{
public DateTime Next();
}