Java JUnit5中的assertAll与多断言
是否有理由将多个断言分组:Java JUnit5中的assertAll与多断言,java,unit-testing,junit,assertions,junit5,Java,Unit Testing,Junit,Assertions,Junit5,是否有理由将多个断言分组: public void shouldTellIfPrime(){ Assertions.assertAll( () -> assertTrue(isPrime(2)), () -> assertFalse(isPrime(4)) ); } 而不是这样做: public void shouldTellIfPrime(){ Assertions.assertTrue(isPrime(2)
public void shouldTellIfPrime(){
Assertions.assertAll(
() -> assertTrue(isPrime(2)),
() -> assertFalse(isPrime(4))
);
}
而不是这样做:
public void shouldTellIfPrime(){
Assertions.assertTrue(isPrime(2));
Assertions.assertFalse(isPrime(4));
}
根据文件 断言所有提供的可执行文件都不会抛出AssertionError 如果提供的任何可执行文件抛出AssertionError,则所有剩余的 可执行文件仍将被执行,所有失败都将被删除 在多个ILURESERROR中聚合和报告。然而,如果 可执行文件抛出的异常不是断言错误, 执行将立即停止,异常将作为 但被伪装为未经检查的异常 因此,主要的区别在于assertAll将允许所有asserts在不中断流的情况下执行,而其他assertTrue和lot将使用AssertionError停止测试 因此,在第一个示例中,无论通过与否,两个断言都将执行,而在第二个示例中,如果第一个断言失败,测试将停止 是否有理由将多个断言分组
如果您希望在单元测试中执行所有断言。有关
assertAll
的有趣之处在于,无论有多少断言失败,它都会执行。如果一切都通过了,一切都很好——如果至少有一个失败了,你就会得到所有错误的详细结果(在这件事上是正确的)
它最好用于断言一组在概念上属于一起的属性。你的第一反应是,“我想把它作为一个整体来断言”
例子
您的具体示例不是assertAll
的最佳用例,因为用素数和非素数检查isPrime
是相互独立的,所以我建议为此编写两种测试方法
但是假设您有一个简单的类,比如一个address,其中包含字段city
,street
,number
,并且希望断言这些字段是您期望的:
Address address = unitUnderTest.methodUnderTest();
assertEquals("Redwood Shores", address.getCity());
assertEquals("Oracle Parkway", address.getStreet());
assertEquals("500", address.getNumber());
现在,一旦第一个断言失败,您将永远看不到第二个断言的结果,这可能会非常恼人。有很多方法可以解决这个问题,JUnit Jupiter的assertAll
就是其中之一:
Address address = unitUnderTest.methodUnderTest();
assertAll("Should return address of Oracle's headquarter",
() -> assertEquals("Redwood Shores", address.getCity()),
() -> assertEquals("Oracle Parkway", address.getStreet()),
() -> assertEquals("500", address.getNumber())
);
如果被测试的方法返回错误的地址,则您将得到以下错误:
org.opentest4j.MultipleFailuresError:
Should return address of Oracle's headquarter (3 failures)
expected: <Redwood Shores> but was: <Walldorf>
expected: <Oracle Parkway> but was: <Dietmar-Hopp-Allee>
expected: <500> but was: <16>
org.opentest4j.MultipleFailuresError:
应返回Oracle总部地址(3次失败)
预期:但是:
预期:但是:
预期:但是:
但不要滥用它!一个单一的测试方法应该总是只测试关于生产代码的一个假设。这就是为什么每个测试方法通常只有一个断言的主要原因。我同意不要滥用它,只测试一个假设,但不同意计数断言有任何价值。这纯粹是一种句法上的考虑,没有任何关联。以我的例子:可能是Address:equals
测试这些属性,在这种情况下,我可以用一个断言来验证它们。从逻辑上讲,这一点都没有区别,但突然之间,它变成了“只有一个断言”。如果我不辞辛劳地为类创建Hamcrest matcher,情况也是如此。“但不同意计数断言有任何价值”,我不建议“计数”断言。每个测试方法一个断言是一个经验法则,不多也不少。。。无论如何,如果你有多个断言,你应该问问自己,你是否真的测试了一个假设。我不完全同意“一个测试,一个断言”的经验法则。它假设被测试的代码是快速且易于运行的。当您的测试从低级单元测试扩展到高级集成测试时,这个假设并不成立。一次运行一段昂贵的代码并对结果运行几个便宜的断言要比多次运行昂贵的代码并每次测试一件事情有效得多。中间点的断言也有助于调试。只要清楚地标记断言,使用多个断言就没有问题。