3

想象一个中等复杂度的 asp.net mvc 应用程序,它使用带有服务层的存储库模式。现在想象我们有一些具有广泛依赖关系的行为。举一个人为的例子:CustomerController 需要显示符合以下所有条件的客户:

  • 客户帐单或送货地址在佛罗里达州
  • 客户在 VIP 俱乐部(使用 ClubMembershipService)
  • 客户至少有一个先前的订单
  • 客户至少拥有一辆 2005 年或更新车型的汽车
  • 这辆车有一个零件被召回
  • 等等,还有更多的一对多或第 3 方 API 调用

此范围的每个测试都需要大量的种子/模拟数据。我的下一个测试可能需要一组相似但明显不同的数据。假设控制器级别的任何测试都需要注入 6 个服务,然后将 8 个存储库注入这些服务。

我怎样才能使我的测试易于管理?如何导航深度对象图并确保模拟(或具体)存储库提供有效、一致的数据,而无需在每个测试中使用 30 行设置代码?

例如,如果这是使用测试数据库的纯集成测试,我可能需要以下内容:

  • 一些客户记录
  • 一些地址记录;一些有多个地址记录的客户;送货地址在佛罗里达州的人;账单地址在佛罗里达州的人
  • 几个订单
  • 一些“CustomerCar”记录;其中一辆车应该有 2005 年或更新的车型
  • 一些“CarPartRecall”记录;其中一些与 CustomerCar 记录的品牌、型号和年份相匹配
  • 依此类推以获取其他标准/逻辑

我知道将这些标准作为属性附加到 Customer 对象可能是有意义的,就像在 customer.IsInVipClub 中一样。我对不能转化为简单属性的复杂案例更感兴趣,因为它们跨越了多个聚合边界。例如customer.Owns2005OrNewerCarWithRecallParts 是我通常不会写的属性。

建议使用 AutoFixture。它看起来像是一个模拟框架和一个夹具工厂之间的交叉点(就像在 factoryGirl 中的 rails 一样)。我认为通过自动提供一些属性值(例如 customer.firstName)会使初始化代码更加简洁,但感觉收益相对较小。我很想听听任何人使用 AutoFixture 的经验。

4

1 回答 1

1

您的问题看起来像一个简单的查询,测试它没有任何价值。并非所有事情都需要统一测试。

如果你真的想测试这个,你可以做一个集成测试。设置一个测试数据库,最好在内存中,插入你的虚拟数据,运行你的查询断言结果并删除虚拟数据。重复每个测试。

对于第 3 方 API 调用,除了模拟它们之外别无他法。

这仍然需要做很多工作,但有些测试更难做,需要更多的工作来构建。

请记住,单元测试需要快速运行。如果它们开始需要更长的时间来运行,它们的运行频率就会降低。另一方面,集成测试可以不时运行,并且可能需要更多时间。

于 2013-10-09T11:10:28.277 回答