该做什么和不该做什么
做
用它们的预期结果和被测试的状态或输入的相关细节来命名测试
别
给测试命名,除了被测试的方法的名称之外什么都不说,除非在微不足道的情况下
结构
三个不同块中的结构测试 -安排、行动和断言。
单元测试往往具有非常规则的结构。引用这种结构的一种常见方式是安排、行动、断言:每个测试都必须安排世界的状态进行测试,通过调用方法作用于被测类,然后断言世界处于预期状态。
安排块用于设置特定于被测情况的外部世界的细节。这涉及到创建将在测试中重用的局部变量,有时还使用特定参数实例化被测对象。此步骤不应涉及对被测对象的任何调用(在动作块期间执行此操作)或初始状态的验证(在断言期间执行此操作,可能在另一个测试中执行)。请注意,所有或许多测试所需的一般设置应在测试的 setUp 方法中完成。如果您的测试不依赖于任何特定的外部状态,您可以跳过排列块。
act 块是您实际调用被测类以触发正在测试的行为的地方。通常这个块将是一个方法调用,但如果您正在测试的行为跨越多个方法,那么它们将在此处被调用。简单的参数可以作为方法调用的一部分内联,但更复杂的参数表达式有时最好提取到排列块中,以避免分散块的意图。act 块还可以将方法的返回值分配给局部变量,以便以后可以对其进行断言。
断言块是对收集的返回值进行断言并验证与模拟对象的任何交互的地方。它还可以构建断言和验证所需的值。在非常简单的测试中,act 和 assert 块有时通过将被测类的调用内联到 assert 语句中来组合。
这些块应该彼此不同——一旦在 act 块中调用被测类,测试不应执行任何额外的设置或存根,并且一旦在断言块。
在查看每个块开始和结束的测试时,应该清楚。通常这可以通过在每个块之间添加一个空行来完成(尽管在每个块只有一到两行的简单测试中这不是必需的)。在特别复杂的测试中,尤其是必须设置多个不同对象的测试中,您可能希望在块中使用空行以使其更具可读性。在这种情况下,区分这些块的一种方法是使用注释标记每个块,例如 // Arrange、//Act 和 // Assert。
强调这种结构的测试更清晰,因为它们可以轻松导航测试的不同部分,并且更有可能完成,因为常规结构有助于确保被测试行为的细节不会被隐藏或省略。
模拟框架以不同的方式与这个结构交互。大多数现代框架(如 Mockito)允许在排列块中配置存根以及定义局部变量,并在断言块中验证模拟以及执行断言。不幸的是,一些像 EasyMock 这样的旧框架需要在调用被测代码之前指定模拟的预期行为 - 这需要在 act 块之前的第四个“expect”块,其工作方式与 assert 块类似。