【问题标题】:State vs Interaction based testing基于状态与交互的测试
【发布时间】:2012-05-28 09:06:57
【问题描述】:

假设我们有一个 Order 类,其中包含一个名为 Approve 的方法。调用此方法时,它会检查某些条件并将 Order 置于 Approved 状态或引发异常。在服务层,我们有这样的东西:

var order = _repository.Single(o => o.ID == orderID);
order.Approve();
_context.SaveChanges(); // or _session.SaveChanges(); 

有两种方法可以测试此方法,我想听听您对此的见解:

解决方案 1:存根存储库以返回 Order 对象。然后断言订单处于“已批准”状态。

解决方案 2:存根存储库以返回一个模拟订单对象。断言 Approve() 方法被调用。

解决方案 1 更简单,我个人更喜欢基于状态的测试而不是基于交互的测试,因为后者可以针对实现细节并且应该避免。但是,我相信测试给定订单是否处于已批准状态不是此服务方法的关注点。我认为我们需要一个单独的 Order 类测试方法来测试是否抛出异常或 Order 的状态是否更改为 Approved。

解决方案 2 可能听起来合乎逻辑,因为我们将批准订单的责任委托给 Order 类本身。所以也许我们需要对这个服务方法进行两项测试:一项确保它将批准订单的任务委托给 Order 类,另一项确保它保存更改。

您对此有何见解?您更喜欢哪种解决方案?

干杯

【问题讨论】:

    标签: unit-testing


    【解决方案1】:

    单元测试是为了测试观察到的行为是否符合预期/规范。

    在这种情况下,您的问题的答案归结为您认为的“预期行为”:a) 如果预期行为是订单在调用服务方法后处于已批准状态,那么测试状态; b) 如果预期行为是授权操作被委派,则测试方法调用。

    您还需要测试Order 对象的行为(以便调用Approve() 将状态更改为已批准)。

    第二种解决方案效果很好,因为它解耦了两个对象的行为,但如果有不止一种方式可以使订单处于已批准状态(这就是您正在测试的——案例 a)),那么您不必要地限制可接受的行为。

    另外,我会创建一个单独的测试来测试保存部分,如果这对于批准部分不是必需的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多