# JUnit

## JUnit

### 前置準備

參考資料:(<https://www.jetbrains.com/help/idea/create-tests.html>)

下載套件:

junit.jar & hamcrest-core.jar(<https://github.com/junit-team/junit4/wiki/Download-and-Install>)

### 第一個測試案例

參考資料:(<http://www.java2s.com/Tutorials/Java/JUnit/0040__JUnit_HelloWorld.htm>)

### 共通事件

參考資料:(<https://ithelp.ithome.com.tw/articles/10192896>)

| name        | static | 說明            |               |
| ----------- | ------ | ------------- | ------------- |
| BeforeClass | O      | 整個開始前執行一次     | 每個case前都會執行一次 |
| After       | X      | 每個case後都會執行一次 |               |
| AfterClass  | O      | 整個測試案例跑完會執行一次 |               |

## 3A原則

在使用@Test註解的方法，即測試案例內編寫：

Arrange：初始化目標物件(待測類別)、初始化相依物件、方法參數、預期結果(excepted)

Act：調用目標物件及欲測試的方法

Assert：驗證實際結果(actual)是否符合預期結果

```
@Test
public void getDirNameTest() {
    // 1. Arrange
    Main m = new Main();
    String src = "./music";
    String excepted = "music";

    // 2. Act
    String actual = m.getDirName(src);

    // 3. Assert
    assertThat(actual).isEqualTo(excepted);}
```

(3A的另外一種描述方式 建造-操作-檢查 BUILD-OPERATE-CHECK)

### Assertj-core 可讀性更好的Assert套件 (jdk8)

參考資料:(<https://ithelp.ithome.com.tw/articles/10193175>)

Github:(<https://github.com/joel-costigliola/assertj-core>)

3.8.0 jar下載點:<http://central.maven.org/maven2/org/assertj/assertj-core/3.8.0/>

2.9.1 jar下載點:<https://jar-download.com/artifacts/org.assertj/assertj-core/2.9.1/source-code>

ERROR Code:

```
java: cannot access java.util.function.Predicate
  class file for java.util.function.Predicate not found
```

經查詢 Predicate 是JDK8新增的項目，根據GitHub內所言

```
Note that AssertJ 3.x requires at least Java 8 and AssertJ 2.x requires at least Java 7.
```

雖然教學文章內是使用 Assertj 3.8.0 ，但我目前只能嘗試JDK7，故接下來皆是改用 2.9.1 的版本。

### 硬斷言和軟斷言

參考文章:(<https://ithelp.ithome.com.tw/articles/10193404>)

軟斷言範例:

```
    @Test
    public void Case4(){
        int actual1 = 5;
        String actual2 = "10";

        SoftAssertions softAssertions = new SoftAssertions();

        softAssertions.assertThat(actual1).isLessThan(4);

        softAssertions.assertThat(actual2).isEqualTo("11");

        softAssertions.assertAll();
    }
```

要記得執行最後一行 `.assertAll()` 才會執行斷言。

#### 注意事項

當我們寫測試的時候，我們必須遵守這樣的原則：

不應在測試方法中加入業務邏輯，不要造成維護上的困難 確保我們的測試易於讀寫

但使用軟斷言： 可能把業務邏輯加入到測試案例中，這會使得讀者的注意力會從測試本質，轉移到實現細節上，也就是說變得難以閱讀。 並且因為業務邏輯加入，當單一狀態的改變時，造成相關的測試也都需要進行變更，這造成維護上的困難。

所以一般情況下是不使用的好...

#### 自訂斷言

參考資料:(<https://ithelp.ithome.com.tw/articles/10193640>)

#### Exception

參考資料:(<https://stackoverflow.com/questions/31423643/try-catch-in-a-junit-test>)

**使用 JUnit 去捕捉，就類似用一個大的 try .. catch 包住這整個Test**

```
@Test(excepted = FileNotFoundException.class)
public void someTest() throws Exception {
    //do something..
}
```

但是上述這個寫法的缺點，在於有可能並不是我們期望的那一行所噴的錯，有可能是其他行噴的，但我們無法察覺。

**使用 AssertJ 編寫斷言**

前置條件：此系統必須是 Java 8

**AssertJ提供了org.assertj.core.api.Assertions.catchThrowable()方法來捕捉異常**

```
@Test
public void example_Exception() {
    Throwable throwable = catchThrowable(()-> throwException());

    assertThat(throwable)
            .isExactlyInstanceOf(Exception.class)
            .hasMessageContaining("Magic");
}

private void throwException() throws Exception {
    throw new Exception("Magic");
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://brianwu.gitbook.io/brian/test/junit.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
