【Java】Junit4からJunit5へ移行

2022年11月18日

はじめに

お世話にになります、hosochinです
最近Junit4からJunit5に移行したのでその時のメモです

Junit4とJunit5の変更点など

Junit5を使う準備

test {
	useJUnitPlatform()
}

testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.7.0'

アノテーション

Junit4Junit5役割
@RunWith, @Ruleなど@ExtendWith拡張機能を読み込む
@Before@BeforeEach各テストメソッドを実行する前に都度実行される
@After@AfterEach各テストメソッドを実行した後に都度実行される
@BeforeClass@BeforeAll各テストクラスを実行する前に実行される
@AfterClass@AfterAll各テストクラスを実行した後に実行される
@Ignore@Disableテスト実行から除外する
@Category@Tagテストケースにカテゴリを付与する

public

Junit5からはテストクラス, テストメソッドにpublicを付与する必要がなくなりました

例外のテスト方法

  • Junit4
    // Junit4
    @Test(expected = RuntimeException.class)
    public void 例外テスト() {
        // テスト対象のメソッド
    }
  • Junit5
    // Junit5
    @Test
    void 例外テスト() {
        Assertions.assertThrows(RuntimeException.class, () -> {
            // テスト対象のメソッド
        });
    }

AssertAllのすすめ

Junit5からAssertAllアノテーションが使えます
1つのアサートに失敗しても後続のアサートは全て実行されます
失敗箇所が一度の実行で全てわかるので何度もテストをやり直す必要もなくおすすめです

  • Junit4
    // Junit4
    @Test
    public void テスト() {
        // テスト対象のメソッド
        List<String> actual = target.execute();

        assertEquals(1, actual.size());    // ここで失敗したらテスト終了
        assertEquals("expected2", actual);   
    }
  • Junit5
    // Junit5
    @Test
    void テスト() {
        // テスト対象のメソッド
        List<String> actual = target.execute();

        assertAll(
                () -> assertEquals(1, actual.size()),    // ここで失敗しても最後までアサートが実行される
                () -> assertEquals("expected2", actual)
        );
    }

DisplayNameのすすめ

Junit5からはDisplayNameというアノテーションが追加されました
こいつはテストレポートに任意のテスト名を付与してくれます
Junit4までは頑張ってメソッド名でテスト内容を表現していたかと思いますが、Junit5からはテスト内容はDisplayNameで表現するのが良さそうです
クラスにも付与できます

@DisplayName("DisplayNameのテスト")
class DisplayNameTest {

    @Test
    @DisplayName("1 テスト")
    void case1() {
        // ...
    }

    @Test
    void case2() {
        // ...
    }

}
  • build/reports/tests/index.html

Nestedのすすめ

Junit5からNestedアノテーションが追加されました
Nestedアノテーションを使ってテストクラスの構造を整理できます
例えばテスト対象クラスのメソッドごとに、テストクラスを分けるなども良さそうです

class NestedTest {

    @Nested
    @DisplayName("method : メソッド1")
    class Method1 {
        @Test
        @DisplayName("正常系")
        void case1() {
            // ...
        }
    }

    @Nested
    @DisplayName("method : メソッド2")
    class Method2 {
        @Test
        @DisplayName("正常系")
        void case1() {
            // ...
        }
    }

ただ個人的にはNested見づらい…テストコードが膨大=分割しないとってことだと思うんですが、そもそも実装クラスに問題あるのでは?とか思っちゃいますよね😎

ParameterizedTestのすすめ

Junit5からParameterizedTestアノテーションが追加されました
こいつは用意されたパラメータの分だけテストメソッドを実行してくれる便利機能で、めちゃめちゃ便利です
詳しくは以下の記事でまとめています

staticメソッドのmock

Junit4はPowerMockを使用した方法が主流っぽいですが、Junit5はPowerMockに対応していないそうです
mockito3.4以降はstaticメソッドをMockできるようになっているのでmockitoを使って実現します
詳細は別の記事にまとめてあるのでこちらを参照お願いしますmm

その他

Junit4で書かれているテストをJunit5で書き直していてちょいちょいミスるんですが、Junit4とJunit5が混ざってると正しく動かないです

import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class Test {

    @Test
    public void test() {

    }

}

こんな感じで@TestはJunit4の方使っちゃってたりみたいな

技術Java,junit,spring

Posted by hosochin