更多註解

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 測試入門

一起來練習吧!

Java 測試入門

Preparing Video For Download...