6.1 斷言
斷言是可以插入代碼不同位置的特殊檢查。他們的任務是確定出了什麼問題。或者更確切地說,檢查一切是否按預期進行。這是“根據需要”,它們允許您以各種方式進行設置。
您已經在上面的代碼中遇到過一些斷言。第一個是檢查對像是否相等。如果對像不相等,將拋出異常並且測試將失敗。
比較的順序在這裡很重要,因為最終報告中的 JUnit 會寫類似“收到值 1,但預期為 3”的內容。這種檢查的一般格式是:
assertEquals(standard , meaning)
例子:
@Test
public void whenAssertingEquality () {
String expected = "3.1415";
String actual = "3";
assertEquals(expected, actual);
}
6.2 方法 assertEquals、assertTrue、assertFalse
下面我將列出最流行的方法——斷言。通過它們的名字很可能猜出它們是如何工作的。但無論如何我都會寫一個簡短的解釋:
斷言等於 | 檢查兩個對像是否相等 |
---|---|
斷言數組相等 | 檢查兩個數組是否包含相等的值 |
assertNotNull | 檢查參數是否不為空 |
斷言為空 | 檢查參數是否為空 |
斷言不相同 | 檢查兩個參數不是同一個對象 |
斷言相同 | 檢查兩個參數是否是同一個對象 |
斷言為真 | 檢查參數是否為真 |
斷言假 | 檢查參數是否為假 |
其中一些方法似乎是多餘的。既然可以寫assertTrue(a == b) ,為什麼還要使用assertSame( a, b ) 呢?
關鍵是assert是一種非常聰明的方法。它做了很多有用的事情,包括將錯誤信息寫入日誌。在第一種情況下,它會寫 object A was expected, but object B was received. 在第二種情況下,它會簡單地寫成true was expected 。
當您有數百個測試時,尤其是那些在專用測試服務器上運行的測試,擁有詳細的日誌會非常有幫助。我想你明白我的意思。
數組比較示例:
@Test
public void whenAssertingArraysEquality() {
char[] expected = {'J','u','n','i','t'};
char[] actual = "Junit".toCharArray();
assertArrayEquals(expected, actual);
}
6.3 assertAll 方法
上面說了,assert方法不僅進行檢查,還會向日誌中寫入很多可比對象的信息。
我們來做個比較:
Address address = unitUnderTest.methodUnderTest();
assertEquals("Washington", address.getCity());
assertEquals("Oracle Parkway", address.getStreet());
assertEquals("500", address.getNumber());
但如果其中一個參數不匹配,則不會檢查其餘參數。但我希望它們仍然發生,並將它們的結果記錄在日誌中。但與此同時,如果至少有一項檢查失敗,則測試仍然失敗。
為此有一個特殊的方法 - assertAll()。作為第一個參數,它需要一條要寫入日誌的註釋,然後是任意數量的斷言函數。
下面是我們的示例將如何用它重寫:
Address address = unitUnderTest.methodUnderTest();
assertAll("Complex address comparison script",
() -> assertEquals("Washington", address.getCity()),
() -> assertEquals("Oracle Parkway", address.getStreet()),
() -> assertEquals("500", address.getNumber())
);
然後如果地址不正確,日誌中將寫入如下內容:
Complex scenario comparison address (3 failures)
expected: <Washington> but was: <Seattle>
expected: <Oracle Parkway> but was: <Main Street>
expected: <500> but was: <5772>
6.4 assertTimeout方法
還記得@Timeout註釋嗎?它允許控制整個方法的執行時間。但有時對方法內部某些部分代碼的執行設置限制是有用的。您可以為此使用assertTimeout()。
時間作為第一個參數傳遞,必須在指定時間內執行的代碼(函數)作為第二個參數傳遞。例子:
@Test
public void whenAssertingTimeout() {
assertTimeout(
ofSeconds(2),
() -> {
// pause for one second
Thread.sleep(1000);
}
);
}
Assert類有assertTimeout()方法的 12 種變體。如果你想了解更多關於它們的信息,歡迎閱讀官方文檔。
6.5 assertThrows 方法
很多情況下,您需要確保在特定情況下代碼拋出正確的異常:它檢測到錯誤並拋出正確的異常。這是一種很常見的情況。
在這種情況下,還有另一個有用的斷言方法——這是assertThrows()。其調用的一般格式為:
assertThrows(exception , code)
基本上,它與assertTimeout()方法非常相似,只是它檢查指定的代碼是否拋出正確的異常。例子:
@Test
void whenAssertingException() {
Throwable exception = assertThrows(
IllegalArgumentException.class,
() -> {
throw new IllegalArgumentException("Exception message");
}
);
assertEquals("Exception message", exception.getMessage());
}