单元测试方法有副作用

时间:2015-02-24 19:48:27

标签: unit-testing

据我所知,“单元测试不应该测试内部实现细节,以免使方法的重构复杂化”。那么,我该如何测试这种方法呢?

deleteOrder = (order) ->
    backendService('deleteOrder', order.id)
    cacheOfOrders.delete(order)

从我的单元测试环境(jasmine)我可以调用deleteOrder并模拟后端调用,但我无法访问cacheOfOrders。我想检查cacheOfOrders.length是否减少了一个。也许我做错了,我不应该测试内部细节,但如果我有一个像前一个方法但没有后端调用怎么办?

2 个答案:

答案 0 :(得分:2)

灵活的解决方案会使您的缓存成为您在此处所做的任何事情的可注入参数,因此您可以传递一个模拟缓存对象,然后您可以对其进行测试。

除此之外,您是否有可用于从缓存中查找订单的方法?您可以声明缓存在deleteOrder调用后没有返回有效条目。如果您的查找在缓存中存在该项时避免了backendService调用,那么您可以测试以确保在删除之后,查找调用实际上确实命中了backendService(这意味着不会填充缓存)。也就是说,测试缓存正常运行的效果,而不是测试缓存本身。

答案 1 :(得分:0)

第一个方面,是否应该测试对缓存的正确处理?是的,由于各种原因。一方面,高速缓存存在是有原因的(可能是性能,如果连接中断则可能具有执行操作的能力……)。此外,缓存消耗内存或其他类型的资源。因此,如果缓存操作不正确,则软件可能无法达到预期的目标,甚至可能由于资源泄漏而在其他地方失败。

第二方面,应如何测试对缓存的正确使用?缓存不会(可能)不会更改代码的功能行为。它可能会改变性能,因此至少可以检查该方面-尽管很难评估是否没有比较数据。而且,对于您作为示例给出的特定功能,它没有帮助,因为它是缓存清理代码,对性能的影响并不明显。

因此,正确的方法是以某种方式使高速缓存可访问或可注入。换句话说,必须以某种方式修改设计以提高可测试性。关键字是可控制性(如果您使高速缓存可注入,而您正在使用控制反转)和/或可观察性(如果您使高速缓存可用于测试)。您所描述的代码都没有。

这将我们带到第三方面(您尚未明确询问),即您的组织实践的单元测试过程是否正确。即(如您在一条评论中所述),有一个专门的单元测试团队,该团队必须按原样测试代码,而不能为了可测试性而进行更改。

也许我不必告诉,因为您是受此折磨的人,但我无法抗拒:这样的单元测试方法无疑是非常不利的。

  • 您观察到的一件事是:来自未编写测试(至少其中一些测试)的开发人员的代码不可测试。这意味着测试工作量更大,尽管测试工作量很大,但仍无法达到预期的程度。
  • 即使测试团队可以执行的测试的价值也较低,因为它们通常会迟到(开发在继续进行,而测试人员仍在尝试测试交付的版本),并且很可能在软件更新完成后移交给测试人员,这将使他们再次花费大量时间才能使用新的软件版本重新编译测试。而且,在这种情况下,对于测试人员来说,甚至甚至不清楚观察到的行为是否有意...
  • 最后,开发人员本身通常不会从这种方法中受益,因为他们甚至无法直接使用测试套件来查看其更改是否导致了回归。

结论:真正的问题是组织设置和测试过程-不幸的是,这可能也是最困难的更改。