1. 程式人生 > >SpringBoot(20)---斷言(Assert)

SpringBoot(20)---斷言(Assert)

#
SpringBoot(20)---斷言(Assert)
我們在寫單元測試的時候,除了介面直接拋異常而導致該單元測試失敗外,還有種是業務上的錯誤也代表著該單元測試失敗。好比我們在測試介面的時候, 該介面返回是1代表成功,如果是0那就代表是失敗的,這個時候可以考慮使用斷言。 ## 一、原理 我們知道,我們可以通過斷言來校驗測試用例的返回值和實際期望值進行比較,以此來判斷測試是否通過。那我們先來看下如果失敗的情況下它的流程是怎麼樣的。 對於斷言而言,如果是錯誤最終都會進入下面的方法 ```java static public void fail(String message) { if (message == null) { throw new AssertionError(); } throw new AssertionError(message); } ``` 很明顯,這裡有一個`AssertionError`物件,我們來看下這個物件。 ``` public class AssertionError extends Error { //...... } ``` 我們很明顯看到,它實繼承是`Error`,而不是**Exception**。這說明什麼,說明你無法通過**try catch**去捕獲這個異常,只要進入斷言fail中,一定會丟擲異常。
## 二、Assert 原始碼 這裡只展示Assert原始碼中常用的方法,一些不常用或者過期的方法這裡就不展示了。 ```java public class Assert { /** * 結果 = 預期 則正確 */ static public void assertEquals(Object expected, Object actual) /** * 結果 != 預期 則正確 */ static public void assertNotEquals(Object unexpected, Object actual) /** * condition == true 則正確 */ static public void assertTrue(boolean condition) /** * condition == false 則正確 */ static public void assertFalse(boolean condition) /** * 永遠是錯誤 */ static public void fail() /** * 結果不為空 則正確 */ static public void assertNotNull(Object object) /** * 結果為空 則正確 */ static public void assertNull(Object object) /** * 兩個物件引用 相等 則正確(上面相當於equels 這裡類似於使用“==”比較兩個物件) */ static public void assertSame(Object expected, Object actual) /** * 兩個物件引用 不相等 則正確 */ static public void assertNotSame(Object unexpected, Object actual) /** * 兩個陣列相等 則正確 */ public static void assertArrayEquals(Object[] expecteds, Object[] actuals) /** * 這個單獨介紹 */ public static void assertThat(T actual, Matcher matcher) } ``` `注意` 上面每一個方法,都會有一個多一個引數的方法,這個引數為:**String message**。意思就是錯誤的情況下,我們可以輸出我們自定義的message **示例** ```java //這個就表示 結果 != 預期 的情況下,丟擲的AssertionError 資訊是我們指定的message static public void assertEquals(String message,Object expected, Object actual) ``` 上面還有一個方法需要單獨介紹,那就是assertThat方法。
## 三、assertThat方法 大家習慣把assertThat理解成`新斷言`,因為上面所以的功能方法,都可以通過assertThat這一個方法來實現。 #### 1、基本語法 assertThat 的基本語法如下: ``` assertThat( [value], [matcher statement] ); ``` **value** 是介面返回資訊中,我們想要測試的變數值 **matcher statement**: 是使用`Hamcrest`匹配符來表達的對前面變數所期望的值的宣告,如果**value**值與**matcher statement**所表達的期望值相符,則測試成功,否則測試失敗。 #### 2、基本使用 `字串匹配符` ```java String n = "xiao"; // containsString:字串變數中包含指定字串時,測試通過 assertThat(n, containsString("xiao")); // startsWith:字串變數以指定字串開頭時,測試通過 assertThat(n, startsWith("xi")); // endsWith:字串變數以指定字串結尾時,測試通過 assertThat(n, endsWith("ao")); // euqalTo:字串變數等於指定字串時,測試通過 assertThat(n, equalTo("xiao")); // equalToIgnoringCase:字串變數在忽略大小寫的情況下等於指定字串時,測試通過 assertThat(n, equalToIgnoringCase("xiao")); // equalToIgnoringWhiteSpace:字串變數在忽略頭尾任意空格的情況下等於指定字串時,測試通過 assertThat(n, equalToIgnoringWhiteSpace(" xiao ")); ``` `int匹配符` ```java int s = 1; // allOf:所有條件必須都成立,測試才通過(大於1同時小於3) assertThat(s, allOf(greaterThan(1), lessThan(3))); // anyOf:只要有一個條件成立,測試就通過 (大於1或者小於2) assertThat(s, anyOf(greaterThan(1), lessThan(2))); // anything:無論什麼條件,測試都通過 assertThat(s, anything()); // is:變數的值等於指定值時,測試通過 assertThat(s, is(2)); // not:和is相反,變數的值不等於指定值時,測試通過 assertThat(s, not(1)); ``` `double匹配符` ```java double d = 1D; // closeTo:浮點型變數的值在3.0±0.5範圍內,測試通過 assertThat(d, closeTo(3.0, 0.5)); // greaterThan:變數的值大於指定值時,測試通過 assertThat(d, greaterThan(3.0)); // lessThan:變數的值小於指定值時,測試通過 assertThat(d, lessThan(3.5)); // greaterThanOrEuqalTo:變數的值大於等於指定值時,測試通過 assertThat(d, greaterThanOrEqualTo(3.3)); // lessThanOrEqualTo:變數的值小於等於指定值時,測試通過 assertThat(d, lessThanOrEqualTo(3.4)); ``` `集合匹配符` ```java List list = new ArrayList(); // hasItem:Iterable變數中含有指定元素時,測試通過 assertThat(list, hasItem("xiao")); Map m = new HashMap<>(); // hasEntry:Map變數中含有指定鍵值對時,測試通過 assertThat(m, hasEntry("xi", "xiao")); // hasKey:Map變數中含有指定key時,測試通過 assertThat(m, hasKey("x")); // hasValue:Map變數中含有指定value值時,測試通過 assertThat(m, hasValue("x")); ```
## 四、測試 這裡對於老斷言,和新斷言各測試5個。 #### 1、老斷言 `示例` ```java public class TestServiceImplTest { @Test public void test1() { String str = "xiao"; assertEquals(str, "xiaoniao");//不相等,所以錯誤 } @Test public void test2() { assertFalse(Boolean.TRUE); //不是false,所以錯誤 } @Test public void test3() { fail("直接是錯誤"); //直接是錯誤 } @Test public void test4() { assertNull("xiao"); //不為空所以為錯誤 } @Test public void test5() { assertNotNull("xiao");//不為空,所以為正確 } } ``` 這裡應該只有第5個測試用例通過,前面4個都不通過的,我們在來看實際執行結果
與實際相符,前面4個,測試用例不通過。而且可以看到第3個是我們自定義錯誤資訊,在控制檯也打印出來了。 #### 2、新斷言 `示例` ```java import org.assertj.core.util.Lists; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.Matchers.*; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; public class TestServiceImplTest { @Test public void test1() { String str = "xiao"; assertThat("這兩字串不相等",str, is("xiaoniao"));//不相等,所以錯誤 } @Test public void test2() { int s = 1; assertThat(s, anyOf(greaterThan(1), lessThan(2)));//滿足 大於1或者小於2 所以正確 } @Test public void test3() { double d = 1D; assertThat(d, allOf(greaterThanOrEqualTo(1D),lessThan(2D)));//滿足大於等於1 並且 小於2 所以正確 } @Test public void test4() { List list = Lists.newArrayList("xiao","zhong","da"); assertThat(list, hasItem("xiao")); //包含xiao 所以正確 } @Test public void test5() { Map map = new HashMap<>(); map.put("xiao", "xiao"); assertThat(map, hasKey("xiao")); //該map包含該key,所以正確 } } ``` 這裡應該只有第1個測試用例不通過,其它都是通過的,我們在來看實際執行結果
符合預期。 好了,整篇文章到這裡就結束了,下面把該專案的具體程式碼放到github上。 `GitHub地址` :[07-test](https://github.com/yudiandemingzi/spring-boot-study)

``` 別人罵我胖,我會生氣,因為我心裡承認了我胖。別人說我矮,我就會覺得好笑,因為我心裡知道我不可能矮。這就是我們為什麼會對別人的攻擊生氣。 攻我盾者,乃我內心之矛(