我正在开发一个具有与此类似的域模型的应用程序,其中a LineItem既可以从a 也可以Order从a 引用Shipment.

如果我使用AutoFixture生成Order,我该如何使用相同的一组LineItems两个order.LineItems和order.Shipments*.ItemShipments*.LineItem?
从理论上讲,以下测试应该通过:
var fullyShippedOrder = fixture.CreateAnonymous<Order>();
var shippedLineItems = fullyShippedOrder.Shipments
.SelectMany(o => o.ItemShipment, (s, i) => i.LineItem)
.Distinct();
Assert.EqualCollection(fullyShippedOrder.LineItems, shippedLineItems);
Run Code Online (Sandbox Code Playgroud)
...虽然我也希望能够根据测试生成部分发货的订单.
(有一个可靠的论据,即订单上的订单项和货件上的订单项是不同的东西,我不应该使用相同的类来表示它们.但是,我正在使用的数据来自遗留系统并没有太多可以做的事情.)
正如您所说,您在测试中遇到的摩擦很可能是域模型中设计问题的一个标志.理想情况下,您应该听取您的测试并从根本上解决问题.但是,鉴于在这种情况下不可行,这是一个解决方法.
您可以使用该方法配置Fixture始终LineItem从固定序列返回对象Register<T>(Func<T> creator).
以下是自定义打包的示例:
public class GenerateLineItemFromFixedSequence : ICustomization
{
public void Customize(IFixture fixture)
{
var items = CreateFixedLineItemSequence(fixture);
fixture.Register(() => GetRandomElementInSequence(items));
}
private static IEnumerable<LineItem> CreateFixedLineItemSequence(IFixture fixture)
{
return fixture.CreateAnonymous<LineItem[]>();
}
private static LineItem GetRandomElementInSequence(IEnumerable<LineItem> items)
{
var randomIndex = new Random().Next(0, items.Count());
return items.ElementAt(randomIndex);
}
}
Run Code Online (Sandbox Code Playgroud)
要在测试的上下文中应用此行为,只需将自定义添加到Fixture对象:
fixture.Customize(new GenerateLineItemFromFixedSequence());
Run Code Online (Sandbox Code Playgroud)
同样,您可以创建其他自定义项,以生成LineItem不同状态的固定对象序列,例如您提到的部分出货订单,并在不同的测试中使用它们.
值得注意的是,这种自定义可以是通用的,因为算法本身并不与正在创建的对象类型相结合.这将有效地将其转化为战略.
因此,通过引入通用参数来修改自定义:
public class GenerateFromFixedSequence<T> : ICustomization
{
public void Customize(IFixture fixture)
{
var items = CreateFixedSequence(fixture);
fixture.Register(() => GetRandomElementInSequence(items));
}
private static IEnumerable<T> CreateFixedSequence(IFixture fixture)
{
return fixture.CreateAnonymous<T[]>();
}
private static T GetRandomElementInSequence(IEnumerable<T> items)
{
var randomIndex = new Random().Next(0, items.Count());
return items.ElementAt(randomIndex);
}
}
Run Code Online (Sandbox Code Playgroud)
允许你将它用于不同的对象:
fixture.Customize(new GenerateFromFixedSequence<LineItem>());
fixture.Customize(new GenerateFromFixedSequence<Order>());
fixture.Customize(new GenerateFromFixedSequence<Shipment>());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
218 次 |
| 最近记录: |