单元测试-相同的方法但针对不同的测试数据

5
这是一个关于单元测试的基础问题。
我有一个方法,例如GetOrderDetails,它调用存储库来获取订单详细信息。我有一个模拟存储库,可以设置为返回固定响应。
为了测试GetOrderDetails方法,我至少会使用以下情况 -
存储库调用失败 1.具有错误代码 2.带有异常
存储库调用成功 1.返回零结果 2.返回一个结果 3.返回多个结果
我应该编写一个单独的测试方法来测试上述情况,还是应该编写单独的测试方法来测试每种情况?
我认为,将其分解成多个测试方法至少会提供以下好处: 1.在测试失败的情况下更高的隔离性 2.测试方法中的代码量较少 3.每个测试方法都将有一个单独的存储库设置责任,例如为无结果设置或为多个结果设置等。
您对此有何看法?
3个回答

8

我建议每个案例都编写一个单独的单元测试。基本上,每当你在测试的方法中编写ifswitch语句时,就需要处理不同的单元测试案例。原因是你的单元测试的安排(arrange)部分将根据你希望代码采取哪种路径而不同(不同的模拟期望、属性设置等)。此外,我建议按以下三个部分组织您的单元测试:

// arrange
// -> prepare mock objects, properties, setup expectations

// act
// -> invoke the method your are testing

// assert
// -> assert on the results returned by the method your are testing

Darin,谢谢。已点赞。我也是和你想得一样。关于if/switch语句的评论非常好。我的所有测试都按照上述方式组织,所以没有问题。通过单独的单元测试,您是指单独的测试方法还是单独的测试类? - byte
@byte,我是指分离测试方法。你可以为另一个被测试类型使用单独的测试类。 - Darin Dimitrov
谢谢。只是想确认您所说的单元测试是否指测试方法、测试类,还是两者都包括。感谢您的回复。 - byte
当为每个if/switch case或参数组合编写单独的单元测试时,我们如何避免CJohnson在他的评论中描述的维护噩梦(请参见下面的第2点)? - byte

3

我知道有些人可能会建立一个基于数据源中不同标准执行的数据驱动测试方法,但我更喜欢个别方法,尤其是这样可以给它一个有意义的名称,比如MethodName_StateUnderTest_ExpectedResult(这是敏捷/单元测试教练和作者Roy Osherove等人推崇的命名约定)。我可以看着名称立即知道通过或失败,而不必想知道可能已经通过或失败的变化。这也有助于我的单元测试不依赖于文件系统。


谢谢Anthony。已点赞。我的测试方法具有一定的数据驱动性,但决策权在于使用哪种数据作为设置/安排的一部分的方法。这些数据更像是XML格式的库存结果/响应,我可以反序列化并在测试方法设置/安排期间使用。 - byte

3
这真的是一个主观性很强的问题,你会得到各种不同的答案。以下是需要记住的几点:
  1. 保持测试代码简短而精炼。我尽量将所有单元测试函数放在一个屏幕中。如果我能做到这一点,那么我就可以在其中放置任何想要的东西。只要上层方法简短,我肯定会在特定函数中测试多个内容。

  2. 复制代码单元测试,只有一个变量不同,会导致维护困难。想象一下,有5个单元测试,每个测试包含40行代码,它们之间唯一的区别是愚蠢的返回值。如果你这样做了,6个月后你会头疼不已。

  3. 在编写单元测试时使用代码覆盖率工具。我无法过分强调这一点。它将帮助您确定未进行测试的区域。我发现它还有助于消除死代码,因为代码越少,潜在的错误就越少。

  4. 我在单元测试中放置的最复杂逻辑只有一个for循环。这仅用于初始化一个简单的数组,如果它对测试有特定作用。我总是避免在单元测试中使用if语句。但是,如果您正在使用数据驱动的测试,则可以使用for循环将数据馈入测试中。但是,如果for循环很小,请随意展开循环。

希望这些建议能对你有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接