AdSense

網頁

2021/4/23

JUnit 測試方法中多個Assertions與assertAll()差別 multi-assertions-assertall-difference

JUnit單元測試有時在一個@Test測試方法中會需要用多個Assertions來驗證,例如回傳結果物件的所有屬性是否皆正確。而直接執行多個Assertions及使用JUnit 5才有的Assertions.assertAll()區別如下。


使用多個Assertions若前面的assert結果錯誤或發生例外,則測試停止,後面的Assertions不會繼續執行。

而使用Assertions.assertAll()群組多個Assertions時,若前面的assert結果錯誤或發生例外,測試不會停止,後面的Assertions仍繼續執行,任一錯務結果會印在MultipleFailuresError訊息中。


例如下面的Main.getEmployeeOfTheYear()是要被測試的程式。

Main

public class Main {

    public Employee getEmployeeOfTheYear() {
        return new Employee(1, "John", 28);
    }
}

MainTests測試類分別在test_multi_assertions()用多個Assertions及在test_assertAll()assertAll()進行測試。

MainTests

public class MainTests {

    private final Main main = new Main();

    @Test
    public void test_multi_assertions() {

        Employee employee = main.getEmployeeOfTheYear();

        Assertions.assertEquals(3, employee.getId());
        Assertions.assertEquals("Mary", employee.getName());
        Assertions.assertEquals(33, employee.getAge());
    }

    @Test
    public void test_assertAll() {

        Employee employee = main.getEmployeeOfTheYear();

        Assertions.assertAll(
                () -> Assertions.assertEquals(3, employee.getId()),
                () -> Assertions.assertEquals("Mary", employee.getName()),
                () -> Assertions.assertEquals(33, employee.getAge())
        );
    }

}

test_multi_assertions()測試結果印出以下。

MainTests.test_multi_assertions()

org.opentest4j.AssertionFailedError: 
Expected :3
Actual   :1
<Click to see difference>


    ...
    at com.abc.demo.MainTests.test_multi_assertions(MainTests.java:15)...
    at java.util.ArrayList.forEach(ArrayList.java:1257)...
    at java.util.ArrayList.forEach(ArrayList.java:1257)...

test_assertAll()測試結果印出以下。

MainTests.test_assertAll()

expected: <3> but was: <1>
Comparison Failure: 
Expected :3
Actual   :1
<Click to see difference>



expected: <Mary> but was: <John>
Comparison Failure: 
Expected :Mary
Actual   :John
<Click to see difference>



expected: <33> but was: <28>
Comparison Failure: 
Expected :33
Actual   :28
<Click to see difference>



org.opentest4j.MultipleFailuresError: Multiple Failures (3 failures)
    org.opentest4j.AssertionFailedError: expected: <3> but was: <1>
    org.opentest4j.AssertionFailedError: expected: <Mary> but was: <John>
    org.opentest4j.AssertionFailedError: expected: <33> but was: <28>
    ...
    at com.abc.demo.MainTests.test_assertAll(MainTests.java:25)...
    at java.util.ArrayList.forEach(ArrayList.java:1257)...
    at java.util.ArrayList.forEach(ArrayList.java:1257)...
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
    Suppressed: org.opentest4j.AssertionFailedError: expected: <3> but was: <1>
        at com.abc.demo.MainTests.lambda$test_assertAll$0(MainTests.java:26)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
        at org.junit.jupiter.api.AssertAll.assertAll(AssertAll.java:77)
        ... 69 more
    Suppressed: org.opentest4j.AssertionFailedError: expected: <Mary> but was: <John>
        at com.abc.demo.MainTests.lambda$test_assertAll$1(MainTests.java:27)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
        at org.junit.jupiter.api.AssertAll.assertAll(AssertAll.java:77)
        ... 69 more
    Suppressed: org.opentest4j.AssertionFailedError: expected: <33> but was: <28>
        at com.abc.demo.MainTests.lambda$test_assertAll$2(MainTests.java:28)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
        at org.junit.jupiter.api.AssertAll.assertAll(AssertAll.java:77)
        ... 69 more

Assertions.assertAll()和拆成多個test方法又有什麼差別呢?Assertions.assertAll()是方便用來測試一個方法同個輸入的輸出結果內含多個值的情況(不過比較物件或許用equals()就好?)。如果輸入不同那應該還是要拆成多個測試方法。


沒有留言:

AdSense