AssertJでよく使うテスト API

# 端書き
- JUnit5のAssertionは優秀だけど、あえてAssertJ
- 普段使ってるものしか書かない
- Mapを使わないので、その検証はない
- Stringやintのみの検証はしない

# 動作環境
- Java8(仕事で使ってる環境なので許して...)
- JUnit5
- Spring Boot: 
- AssertJ: 3.14.0

ソースは[こちら](https://github.com/ririkku/assertj-sandbox)


# 独自クラス系

## オブジェクトのフィールドを再帰的に検証

`usingRecursiveComparison`を付与することで、入れ子になっているクラスの検証で、インスタンス比較にならないようにする


```.java
@Test
void オブジェクトのフィールドを再帰的に検証() {
    String studentIdentifier = generateUUID();
    String tutorIdentifier = generateUUID();
    Lesson actual = new Lesson(
        new Student(new StudentIdentifier(studentIdentifier), new StudentName("studentName")),
        new Tutor(new TutorIdentifier(tutorIdentifier), new TutorName("tutorName")));
    Lesson expected = new Lesson(
        new Student(new StudentIdentifier(studentIdentifier), new StudentName("studentName")),
        new Tutor(new TutorIdentifier(tutorIdentifier), new TutorName("tutorName")));
    Assertions.assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
}
```

## 複数を一気に

```.java
@Test
void 検証を途中で終わらせない() {
    String studentIdentifier = generateUUID();
    String tutorIdentifier = generateUUID();
    Lesson actual = new Lesson(
        new Student(new StudentIdentifier(studentIdentifier), new StudentName("studentName")),
        new Tutor(new TutorIdentifier(tutorIdentifier), new TutorName("tutorName")));
    SoftAssertions softAssertions = new SoftAssertions();
    softAssertions.assertThat(actual.student().identifier().value()).as("OK").isEqualTo(studentIdentifier);
    softAssertions.assertThat(actual.student().name().value()).as("NG").isEqualTo("x");
    softAssertions.assertThat(actual.tutor().identifier().value()).as("OK").isEqualTo(tutorIdentifier);
    softAssertions.assertThat(actual.tutor().name().value()).as("OK").isEqualTo("tutorName");
    softAssertions.assertAll();
}
```

# Collection系

## サイズ

```.java
@Test
void サイズの検証() {
    List<String> actual = Arrays.asList("a", "b", "c");
    Assertions.assertThat(actual).hasSize(3);
}
```

## 全要素

extractingで生成したTupleのIterable全ての要素を含んでいない場合は検証エラーになる

```.java
@Test
void 全要素の検証() {

    // 1つ目のLessonを生成
    String student1Identifier = generateUUID();
    String tutor1Identifier = generateUUID();
    Lesson lesson1 = new Lesson(
            new Student(new StudentIdentifier(student1Identifier), new StudentName("student1")),
            new Tutor(new TutorIdentifier(tutor1Identifier), new TutorName("tutor1")));

    // 2つ目のLessonを生成
    String student2Identifier = generateUUID();
    String tutor2Identifier = generateUUID();
    Lesson lesson2 = new Lesson(
            new Student(new StudentIdentifier(student2Identifier), new StudentName("student2")),
            new Tutor(new TutorIdentifier(tutor2Identifier), new TutorName("tutor2")));

    Lessons actual = new Lessons(Arrays.asList(lesson1, lesson2));
    Assertions.assertThat(actual.list())
            .usingRecursiveFieldByFieldElementComparator()
            // 全ての値の検証、並び順はなんでもいい
            .containsOnly(
                    new Lesson(new Student(new StudentIdentifier(student2Identifier), new StudentName("student2")), new Tutor(new TutorIdentifier(tutor2Identifier), new TutorName("tutor2"))),
                    new Lesson(new Student(new StudentIdentifier(student1Identifier), new StudentName("student1")), new Tutor(new TutorIdentifier(tutor1Identifier), new TutorName("tutor1"))));
}
```

## 順番

```.java
@Test
void 順番の検証() {
    // 1つ目のLessonを生成
    String student1Identifier = generateUUID();
    String tutor1Identifier = generateUUID();
    Lesson lesson1 = new Lesson(
            new Student(new StudentIdentifier(student1Identifier), new StudentName("student1")),
            new Tutor(new TutorIdentifier(tutor1Identifier), new TutorName("tutor1")));

    // 2つ目のLessonを生成
    String student2Identifier = generateUUID();
    String tutor2Identifier = generateUUID();
    Lesson lesson2 = new Lesson(
            new Student(new StudentIdentifier(student2Identifier), new StudentName("student2")),
            new Tutor(new TutorIdentifier(tutor2Identifier), new TutorName("tutor2")));

    // 3つ目のLessonを生成
    String student3Identifier = generateUUID();
    String tutor3Identifier = generateUUID();
    Lesson lesson3 = new Lesson(
            new Student(new StudentIdentifier(student3Identifier), new StudentName("student3")),
            new Tutor(new TutorIdentifier(tutor3Identifier), new TutorName("tutor3")));

    Lessons actual = new Lessons(Arrays.asList(lesson1, lesson2, lesson3));

    Assertions.assertThat(actual.list())
            .usingRecursiveFieldByFieldElementComparator()
            // 全ての値の検証
            .containsExactly(
                    new Lesson(new Student(new StudentIdentifier(student1Identifier), new StudentName("student1")), new Tutor(new TutorIdentifier(tutor1Identifier), new TutorName("tutor1"))),
                    new Lesson(new Student(new StudentIdentifier(student2Identifier), new StudentName("student2")), new Tutor(new TutorIdentifier(tutor2Identifier), new TutorName("tutor2"))),
                    new Lesson(new Student(new StudentIdentifier(student3Identifier), new StudentName("student3")), new Tutor(new TutorIdentifier(tutor3Identifier), new TutorName("tutor3"))));
}
```

## 一部の値

```.java
@Test
void オブジェクトの一部の値を取り出して検証() {
    // 1つ目のLessonを生成
    Lesson lesson1 = new Lesson(
            new Student(new StudentIdentifier(generateUUID()), new StudentName("student1")),
            new Tutor(new TutorIdentifier(generateUUID()), new TutorName("tutor1")));

    // 2つ目のLessonを生成
    Lesson lesson2 = new Lesson(
            new Student(new StudentIdentifier(generateUUID()), new StudentName("student2")),
            new Tutor(new TutorIdentifier(generateUUID()), new TutorName("tutor2")));

    Lessons actual = new Lessons(Arrays.asList(lesson1, lesson2));
    Assertions.assertThat(actual.list())
            // Iterableの要素を分解して新たにTupleのIterableを作る
            .extracting(
                    lesson -> lesson.student().name().value(),
                    lesson -> lesson.tutor().name().value())
            // 全ての値の検証、並び順はなんでもいい
            .containsOnly(
                    // Tupleで検証
                    Tuple.tuple("student2", "tutor2"),
                    Tuple.tuple("student1", "tutor1"));
}
```




# 例外

## 正しい例外か

あえて`assertThatExceptionOfType`を使っているけど、
- assertThatNullPointerException
- assertThatIllegalArgumentException
- assertThatIllegalStateException
- assertThatIOException
は個別に用意されている

```.java
@Test
void 例外を受け取る() {
    Assertions.assertThatExceptionOfType(IOException.class)
            .isThrownBy(() -> {
                throw new IOException("IOException Message");
            })
            .withMessage("%s Message", "IOException")
            .withMessageContaining("IOException")
            .withNoCause();
}
```

ぬるぽだけ書いてみた

```.java
@Test
void ぬるぽ専用() {
    Assertions.assertThatNullPointerException().isThrownBy(() -> { throw new NullPointerException("ぬるぽ がっ"); })
            .withMessage("ぬるぽ %s", "がっ")
            .withMessageContaining("がっ")
            .withNoCause();
}
```


# あとがき
何か頻繁に使うものが増えたら追記しよう
オススメがあればコメントください