单元测试无效方法


15

为了修复应用程序中的错误,我postLogin通过将调用添加到名为的现有方法上来修改了一种名为的方法getShoppingCart

protected void postLogin() {
  getShoppingCart();
}

但是,我不确定编写单元测试的最佳方法postLogin是什么。

方法1

使用Mockito中的verify可以简单地验证该方法是否已被调用。

verify(mock).getShoppingCart();

方法2

通过获取用户购物车的值来测试方法调用的副作用。

AssertNotNull(user.getShoppingCart());

一种方法比另一种更好吗?


1
两者使测试更容易理解,并保持代码干净。如果您不确定测试设计,即COULD也是一个标志,代码设计是关闭的。确保您在问以下问题:“ 为什么添加该方法调用可以修复该错误?这是修复此错误的正确方法吗?”
卡雷布(Caleb)

8
除非您的getShoppingCart()方法有副作用,否则您无需测试它是否被调用。如果确实有副作用,则应真正更改其名称,因为getXXX()传统上方法应是幂等的。
Jules

@Jules getNextValue?可以说,有人会说“不要称它为吸气剂;将名称更改为nextValue”,但是我以前见过getNext。也许更好的例子是代表电子的物体。我打电话时会getPosition怎样?或更糟糕的是,getPosition(); getVelocity();
亚伦

Answers:


18

我通常更喜欢方法2。

为什么?因为,您想postLogin更改系统的某些状态,但是它如何完成此操作(以及它内部为此调用的方法)仅是实现细节,因此您的单元测试不应做任何假设。因此最好只验证最终状态就可以进行测试。


4

我会将getShoppingCart更改为InitializeShoppingCart之类的方法,该方法的目的应该对任何阅读它的人来说都很清楚,而无需检查该方法的作用,并且这种副作用可能会给该方法的用户带来一些令人惊讶的行为。

如果getShoppingCart在另一个类中并且已经过单元测试,则可以使用方法1-无需再次测试已测试的内容。在这种情况下,我们确定getShoppingCart可以正常工作,并且我们只想确保从postLogin调用了它,因此,如果将来有人删除此调用,则测试将失败。

如果getShoppingCart是无法自行测试的私有方法,那么我将使用方法2,以确保在调用postLogin时,可以按预期执行getShoppingCart的所需功能。


1

测试具有副作用的函数调用(是否无效)时,最完整的方法是测试不仅会发生副作用,而且还要检查副作用(系统输出或状态更改)是否是所需的。


1
虽然这是事实,但也值得考虑的是,发生副作用的详细信息可能是其他模块内部状态的一部分,并且通过检查这些详细信息,您不仅可以将测试耦合到模块上,还可以它正在测试,而且还在测试其他模块,如果这些细节可能会更改,则可能导致脆弱的测试。模拟模块之间的接口有助于防止此问题。
Jules

0

我不会讨论您的设计,但是对于您而言,我将采用第一种方法,因为单元测试用于测试无论哪种方法在领域中均会在技术上执行哪些方法,也就是说,您的方法会postLogin做什么?从技术上讲,它需要调用,getShoppingCard因此您必须测试实际上是在调用getShoppingCard,我还将创建另一个测试getShoppingCard以测试它的功能,以及是否有副作用,我将在新测试中对其进行检查。


0

您在postLogin中有一个错误。因此,您应该做的第一件事是创建一个单元测试,该单元测试在调用postLogin而不提供预期的信息集时将“失败”。

根据以上想法,建议的2的另一种替代方法是注入有关购物车的信息作为参数。如果没有正确的信息,则会引发未经检查的异常。这将清楚地表明,如果没有正确的细节,您的方法将注定失败。

这将需要进行一些更改,其中要求立即调用postLogin的客户端还传递购物车信息。对我来说,这仍然是连贯的,因为您看到它们是耦合的。此耦合将由调用方完成。

然后,您甚至不需要在postLogin内测试getShoppingCart,因为真正的测试方法是postLogin。这是一个存在错误的程序,也是唯一需要适当修复和验证的程序。使用注入的依赖项,您将能够在不同的条件下轻松对其进行测试,并确认没有引发任何错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.