追加のアノテーション

Javaによるテスト入門

Maria Milusheva

Senior Software Engineer

前提: .of() でのオブジェクト生成

次を考えます:

List<Integer> newList = new ArrayList<Integer>();
newList.add(10);
newList.add(20);
newList.add(30);

より速く短い書き方:

List<Integer> newList = List.of(10, 20, 30);
  • Java Collections の SetMap でも同様に動作

  • .of() で作成したオブジェクトは通常イミュータブル(変更不可)

Javaによるテスト入門

@ParameterizedTest へのオブジェクト渡し

次のクラスを考えます:

class Person {
    String firstName;
    String lastName;
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    public String fullName(Person person) {
        return firstName + " " + lastName;
    }
}
Javaによるテスト入門

Arguments クラス

複数の型の引数を渡すには Arguments を使います。

Arguments は任意数・任意型のオブジェクトを含められます。

例:

Arguments.of(new Person("Monty", "Python"), "Monty Python");

これを次の @ParameterizedTest で使えます。

Javaによるテスト入門

@MethodSource

@MethodSource は任意のオブジェクトをテストに渡せます。

テストは次のようになります:

@ParameterizedTest
@MethodSource("provideNames")
void testFullName(Person person, String expectedFullName) {
    assertEquals(person.fullName(person), expectedFullName);
}
Javaによるテスト入門

@MethodSource の提供メソッド

@MethodSource 用のメソッド:

private static List<Arguments> provideNames() {
    List<Arguments> args = new ArrayList<>();
    args.add(Arguments.of(new Person("Robert", "Martin"), "Robert Martin"));
    args.add(Arguments.of(new Person("Heinz", "Kabutz"), "Heinz Kabutz"));

    return args;
}

注意: メソッドは static が必要

注意: 許可される戻り値型は多数。最も簡単なのは List<Arguments>

1 https://junit.org/junit5/docs/5.2.0/api/org/junit/jupiter/params/provider/MethodSource.html
Javaによるテスト入門

@MethodSource の提供メソッド

@MethodSource 用のメソッド:

private static List<Arguments> provideNames() {
    return List.of(
        Arguments.of(new Person("John", "Doe"), "John Doe"),
        Arguments.of(new Person("Jane", "Doe"), "Jane Doe"),
        Arguments.of(new Person("Alice", "Bob"), "Alice Bob"));
}
Javaによるテスト入門

引数以外も必要な場合は?

次のデータベース向けテストを考えます:

@Test
void process_savesToInfoStore_whenInfoMessage() {
  InfoStore infoStore = mock(InfoStore.class);
  ErrorStore errorStore = mock(ErrorStore.class);
  MessageProcessor messageProcessor = new MessageProcessor(infoStore, errorStore);

messageProcessor.saveMessage("[INFO] Process started.");
verify(infoStore).save("[INFO] Process started."); verifyNoInteractions(errorStore); }
Javaによるテスト入門

@BeforeEach アノテーション

@BeforeEach を使うと、各テストの前に実行されるメソッドを作れます:

import org.junit.jupiter.api.BeforeEach;

使うには、まずオブジェクトをフィールドとして宣言します:

class MessageProcessorTest {

    private InfoStore infoStore;
    private ErrorStore errorStore;
    private MessageProcessor messageProcessor;
Javaによるテスト入門

@BeforeEach 用メソッド

各オブジェクトを専用メソッドで生成します:

@BeforeEach
void setUp() {
    this.infoStore = mock(InfoStore.class);
    this.errorStore = mock(errorStore.class);
    this.messageProcessor = new MessageProcessor(infoStore, errorStore);
}
Javaによるテスト入門

短くしたテスト

テストクラスは次のように簡潔になります:

@Test
void process_savesToInfoStore_whenInfoMessage() {
    messageProcessor.process("[INFO] Process started.");

    verify(infoStore).save("[INFO] Process started."); 
    verifyNoInteractions(errorStore); 
}
Javaによるテスト入門

@BeforeEach の全体フロー

まとめ:

class MessageProcessorTest {
    private InfoStore infoStore; // フィールドを宣言


@BeforeEach void setUp() { this.infoStore = mock(InfoStore.class); // フィールドを初期化 }
@Test void process_savesToInfoStore_whenInfoMessage() { // フィールドを使用 } }
Javaによるテスト入門

Passons à la pratique !

Javaによるテスト入門

Preparing Video For Download...