Junit　どうやって使うの…？　初学者向け


　今回仕事でJunitを使用することになり初めて使用するためアウトプットとしてまとめてみました。記事に間違いがある場合はコメントしていただけると幸いです。
## JUnitとは

> JUnitとは、Java言語で開発されたプログラムの単体テスト（ユニットテスト）を行なうためのソフトウェア。また、そこで用いられるテストコードの記述体系を含むテストフレームワーク。  
> IT用語辞典 e-Wordsより

つまり、Javaで使用する便利なテストツールだと言えますね！

JUnitにはユニットテストを行うために以下のような便利な機能が用意されています。
* アノテーション
* メソッド

まずは機能を説明する前にテストをするコードとテストコードを見ていきましょう。

## テスト Level.1
### テストするコード
```java
public class FizzBuzz {
    
    public String FizzBuzz (int number) {
        String str = "";
        if (number % 3 == 0) {
            str += "Fizz";
        }
        if (number % 5 == 0) {
            str += "Buzz";
        }
        return str;
    }   
}
```

上記のコードは以下の仕様になっています。

* 入力された値が3で割り切れる場合は"Fizz"
* 入力された値が5で割り切れる場合は"Buzz"
* 入力された値が3と5で割り切れる場合は"FizzBuzz"
* 入力された値が3と5で割り切れない場合は空文字

このコードに対してどのようなテストコードを書けばいいでしょうか？

まずはテストケースを考えてみましょう。

### テストケース
1. 3で割り切れるが5で割り切れない値
2. 3で割り切れないが5で割り切れる値
3. 3でも5でも割り切れる値
4. 3でも5でも割り切れない値  

### テストコード
```java
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

public class FizzBuzzTest {
    
    @Test
    public void testFizzBuzz() {
        FizzBuzz fizzBuzz = new FizzBuzz();
        
        // 3の倍数の場合
        assertEquals("Fizz", fizzBuzz.FizzBuzz(3), "3の倍数の場合Fizzが返されるべき");
        assertEquals("Fizz", fizzBuzz.FizzBuzz(9), "9の倍数の場合Fizzが返されるべき");
        
        // 5の倍数の場合
        assertEquals("Buzz", fizzBuzz.FizzBuzz(5), "5の倍数の場合Buzzが返されるべき");
        assertEquals("Buzz", fizzBuzz.FizzBuzz(10), "10の倍数の場合Buzzが返されるべき");
        
        // 3と5の倍数の場合
        assertEquals("FizzBuzz", fizzBuzz.FizzBuzz(15), "15の倍数の場合FizzBuzzが返されるべき");
        assertEquals("FizzBuzz", fizzBuzz.FizzBuzz(30), "30の倍数の場合FizzBuzzが返されるべき");
        
        // どちらの倍数でもない場合
        assertEquals("", fizzBuzz.FizzBuzz(7), "7のようにどちらの倍数でもない場合は空文字が返されるべき");
        assertEquals("", fizzBuzz.FizzBuzz(1), "1のようにどちらの倍数でもない場合は空文字が返されるべき");
    }
}
```

`@Test`アノテーションがありますね。`@Test`アノテーションは、JUnitフレームワークにおいてテストメソッドを示すために使用されるアノテーションです。このアノテーションが付けられたメソッドは、JUnitによってテストとして実行されます。JUnitは、`@Test`アノテーションを持つメソッドを検出し、これらのメソッドを実行してテスト結果を報告します。

### アサーションメソッドの説明
```java
static void assertEquals(Object expected, Object actual, String message)
```
- `expected`：予想される結果。
- `actual`：実際の結果。
- `message`：テストが失敗した場合に表示されるメッセージ（省略可能）。

## テスト Level.2 (CRUD操作)
### テストするコード

まず、Userエンティティクラスを定義します。
```java
class User {
    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
```
Userを定義するエンティティクラスです。エンティティが分からない場合はMVCモデルやデータベースを学んでみると良いでしょう！

次に、CRUD操作を行うサービスクラスを定義します。
```java
import java.util.*;

public class UserService {
    private Map<Integer, User> users = new HashMap<>();
    private int nextId = 1;

    public User createUser(String name) {
        User user = new User(nextId++, name);
        users.put(user.getId(), user);
        return user;
    }

    public User getUser(int id) {
        return users.get(id);
    }

    public List<User> getAllUsers() {
        return new ArrayList<>(users.values());
    }

    public User updateUser(int id, String name) {
        User user = users.get(id);
        if (user != null) {
            user.setName(name);
        }
        return user;
    }

    public boolean deleteUser(int id) {
        return users.remove(id) != null;
    }
}
```

### テストコード
次に、JUnitを用いてこのサービスクラスのテストを行います。
```java
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

public class UserServiceTest {

    private UserService userService;

    @BeforeEach
    public void setUp() {
        userService = new UserService();
    }

    @Test
    public void testCreateUser() {
        User user = userService.createUser("John Doe");
        assertNotNull(user, "User should not be null");
        assertEquals("John Doe", user.getName());
        assertTrue(user.getId() > 0, "User ID should be greater than 0");
    }

    @Test
    public void testGetUser() {
        User createdUser = userService.createUser("Jane Doe");
        User fetchedUser = userService.getUser(createdUser.getId());
        assertNotNull(fetchedUser, "Fetched user should not be null");
        assertEquals(createdUser.getId(), fetchedUser.getId());
        assertEquals("Jane Doe", fetchedUser.getName());
    }

    @Test
    public void testGetAllUsers() {
        userService.createUser("Alice");
        userService.createUser("Bob");
        List<User> users = userService.getAllUsers();
        assertEquals(2, users.size(), "There should be 2 users");
    }

    @Test
    public void testUpdateUser() {
        User user = userService.createUser("Charlie");
        User updatedUser = userService.updateUser(user.getId(), "Charlie Updated");
        assertNotNull(updatedUser, "Updated user should not be null");
        assertEquals("Charlie Updated", updatedUser.getName());
    }

    @Test
    public void testDeleteUser() {
        User user = userService.createUser("Dave");
        boolean isDeleted = userService.deleteUser(user.getId());
        assertTrue(isDeleted, "User should be deleted successfully");
        assertNull(userService.getUser(user.getId()), "Deleted user should not be found");
    }
}
```

## テストメソッドの解説
### 1. `setUp`メソッド
各テストメソッドの実行前に毎回呼ばれ、`userService`の新しいインスタンスを作成します。これにより、テストが相互に影響を与えないようにします。

### 2. `testCreateUser`メソッド
ユーザーの作成をテストし、ユーザーオブジェクトが正しく作成されていることを確認します。

### 3. `testGetUser`メソッド
ユーザーの取得をテストし、作成されたユーザーが正しく取得できることを確認します。

### 4. `testGetAllUsers`メソッド
全ユーザーの取得をテストし、正しい数のユーザーが返されることを確認します。

### 5. `testUpdateUser`メソッド
ユーザーの更新をテストし、ユーザー名が正しく更新されることを確認します。

### 6. `testDeleteUser`メソッド
ユーザーの削除をテストし、ユーザーが正しく削除されることを確認します。

## アサーションメソッドの説明

### `assertNotNull`
`assertNotNull`は指定されたオブジェクトが`null`でないことを確認します。このアサーションが失敗すると、テストが失敗し、そのオブジェクトが`null`であったことを示します。

```java
User user = userService.createUser("John Doe");
assertNotNull(user, "User should not be null");
```
この例では、`userService.createUser("John Doe")`が`null`でないことを確認しています。もし`null`であれば、テストは失敗し、メッセージ `"User should not be null"` が表示されます。

### `assertTrue`
`assertTrue`は指定された条件が`true`であることを確認します。このアサーションが失敗すると、テストが失敗し、その条件が`false`であったことを示します。

```java
boolean isDeleted = userService.deleteUser(user.getId());
assertTrue(isDeleted, "User should be deleted successfully");
```
この例では、`userService.deleteUser(user.getId())`の結果が`true`であることを確認しています。もし結果が`false`であれば、テストは失敗し、メッセージ `"User should be deleted successfully"` が表示されます。

## まとめ
JUnitを用いることで、Javaプログラムのユニットテストを効率的に行うことができます。JUnitには以下のような便利な機能が用意されています。

- **アノテーション**: テストメソッドを指定する`@Test`や、テスト前に実行するメソッドを指定する`@BeforeEach`などがあります。
- **アサーションメソッド**: `assertEquals`や`assertNotNull`、`assertTrue`など、さまざまな条件を確認するためのメソッドがあります。

### テストの流れ
1. **テストケースの考案**: どのような入力に対してどのような出力が期待されるかを考えます。
2. **テストメソッドの作成**: `@Test`アノテーションを用いて、テストメソッドを定義します。
3. **アサーションの使用**: `assertEquals`や`assertNotNull`、`assertTrue`などのアサーションメソッドを用いて、期待される結果と実際の結果を比較します。
4. **テストの実行**: JUnitテストを実行し、テストが成功するか確認します。

## 参考文献
JUnitの詳細なドキュメントやその他のリソースは、公式サイトや関連するJavaの書籍を参照すると良いでしょう。また、実際にコードを書いてテストを実行してみることで、JUnitの使い方をより深く理解することができます。

JUnit公式サイト: [https://junit.org/junit5/](https://junit.org/junit5/)