虽然本文中的示例是使用 JUnit 5 和 AssertJ 编写的,但这些课程适用于任何其他单元测试框架。
JUnit 是 Java 最流行的测试框架。AssertJ 是一个 Java 库,可帮助开发人员编写更具表现力的测试。
基本测试结构
我们将要看的第一个测试示例是一个用于将两个数字相加的简单计算器。
计算器类应该{
@测试 // 1
无效总和(){
计算器 calculator = new Calculator(); // 2
int 结果 = 计算器.sum(1, 2); // 3
断言(结果).isEqualTo(3); // 4
}
}
我更喜欢在编写测试时使用ClassShould命名约定,葡萄牙电话号码库 以避免在每个方法名称中重复should。您可以在此处test阅读更多相关信息。
上面的测试起什么作用?
让我们逐行分解测试:
@Test注释让 JUnit 框架知道哪些方法应该作为测试运行。private测试类中存在不是测试的方法是完全正常的。
这是我们测试的安排阶段,我们在此准备测试环境。本次测试所需的只是一个Calculator实例。
这是我们触发想要测试的行为的行为阶段。
这是断言阶段,我们检查发生了什么以及一切是否都按预期解决。assertThat(result)方法是 AssertJ 库的一部分,并且有多个重载。
每个重载都会返回一个专门的Assert对象。返回的对象具有对我们传递给方法的对象有意义的方法assertThat。在我们的例子中,该对象具有AbstractIntegerAssert用于测试整数的方法。isEqualTo(3)将检查是否result == 3。如果是,则测试将通过,否则将失败。
我们不会在这篇博文中关注任何实现。
关于安排、行动、断言的另一种思考方式是给定、何时、然后。
编写sum实现后,我们可以问自己一些问题:
我怎样才能提高这次考试的成绩?
我还应该涵盖更多的测试用例吗?
如果我把一个正数和一个负数相加会发生什么?两个负数?一个正数和一个负数?
如果我溢出了整数值怎么办?
让我们添加这些案例并稍微改进现有的测试名称。
我们的实现不允许溢出。如果sum溢出,我们将抛出一个ArithmeticException。
计算器类应该{
私人计算器计算器=新计算器();
@测试
无效总和正数(){
int sum = 计算器.sum(1, 2);
断言(sum).isEqualTo(3);
}
@测试
void sumNegativeNumbers() {
int 总和 = 计算器.总和(-1,-1);
断言(sum).isEqualTo(-2);
}
@测试
void sumPositiveAndNegativeNumbers() {
int 总和 = 计算器.总和(1, -2);
断言(sum).isEqualTo(-1);
}
@测试
void failWithArithmeticExceptionWhenOverflown(){
assertThatThrownBy(() -> 计算器.sum(Integer.MAX_VALUE, 1))
.isInstanceOf(ArithmeticException.class);
}
}
CalculatorShouldJUnit 将在运行每个方法之前创建一个新的实例@Test。这意味着每个方法CalculatorShould都会有不同的实例calculator,因此我们不必在每个测试中都实例化它。
shouldFailWithArithmeticExceptionWhenOverflowntest 使用不同类型的assert。它检查一段代码是否失败。assertThatThrownBy方法将运行我们提供的 lambda 并确保它失败。我们已经知道,所有assertThat方法都会返回一个专门的Assert,允许我们检查发生了哪种类型的异常。
这是一个示例,说明我们如何测试代码是否按预期失败。如果我们在任何时候进行重构Calculator,但代码没有抛出ArithmeticException溢出,我们的测试就会失败。
阅读编写可测试代码