你最初的尝试看起来不错,但至少有一些事情你可以简化一点。
首先,您应该能够减少:
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
变量。类型推断将发现由于func的返回类型,您正在注册计划。
但是,假设调度构造函数如下所示:
public Schedule(IEnumerable<CarrierMovement> carrierMovements)
你可以直接注册
carrierMovements
这样地:
fixture.Register<IEnumerable<CarrierMovement>>(carrierMovements);
这将导致自动修复自动解决正确的时间表。这种方法更易于维护,因为它允许您将来在不破坏测试的情况下向调度构造函数添加参数(只要autofixture可以解析参数类型)。
但是,在这种情况下,我们可以做得更好,因为我们没有真正使用
搬运
变量,用于注册以外的任何内容。我们真正需要做的只是告诉Autofixture如何创建
IEnumerable<CarrierMovement>
. 如果您不关心数字50(您不应该关心),我们甚至可以使用如下方法组语法:
fixture.Register(fixture.CreateMany<CarrierMovement>);
注意缺少方法调用paranthess:我们注册了一个func,自从
CreateMany<T>
方法返回
IEnumerable<T>
类型推断处理剩下的。
然而,这些都是细节。在更高的层次上,您可能会考虑根本不注册carriermovement。假设此构造函数:
public CarrierMovement(Location departureLocation,
Location arrivalLocation,
DateTime departureTime,
DateTime arrivalTime)
自动修复应该能够自己解决。
它将为每个出发地点和到达地点创建一个新的地点实例,但这与您在原始测试中手动执行的操作没有区别。
当涉及到时间时,默认情况下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());
但是,既然您问了这个问题,我的意思是调度构造函数如下所示:
public Schedule(IList<CarrierMovement> carrierMovements)
我真的认为你应该重新考虑改变API
IEnumerable<Carriemovement>
. 从API设计的角度来看,通过任何成员(包括构造函数)提供集合意味着允许该成员修改集合(例如,通过调用其添加、删除和清除方法)。这几乎不是您期望从构造函数得到的行为,所以不要允许这样做。
Autofixture将自动为所有
Location
上面例子中的对象,但是由于CPU的速度,日期时间的后续实例可能是相同的。
如果希望增加日期时间,可以编写一个小类,每次调用返回的日期时间都会增加该类。我将把该类的实现留给感兴趣的读者,但是您可以这样注册它:
var dtg = new DateTimeGenerator();
fixture.Register(dtg.Next);
假设使用此API(请再次注意上面的方法组语法):
public class DateTimeGenerator
{
public DateTime Next();
}