Java 測試入門
Maria Milusheva
Senior Software Engineer
想想看:
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 的 Set 與 Map 同樣適用
以 .of() 建立的物件通常是不可變(不能更動)
請看下列類別:
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;
}
}
我們用 Arguments 來傳入任意型別的多個參數。
Arguments:可包含任意數量、任意型別的物件。
例如:
Arguments.of(new Person("Monty", "Python"), "Monty Python");
接著就能在下一種 @ParameterizedTest 中使用。
@MethodSource 允許我們將任何物件傳入測試。
測試如下:
@ParameterizedTest
@MethodSource("provideNames")
void testFullName(Person person, String expectedFullName) {
assertEquals(person.fullName(person), expectedFullName);
}
@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> 最簡單
@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"));
}
來看這個資料庫測試:
@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); }
我們可以用 @BeforeEach 註解建立一個在每個測試前執行的方法:
import org.junit.jupiter.api.BeforeEach;
要使用它,先把物件宣告為欄位:
class MessageProcessorTest {
private InfoStore infoStore;
private ErrorStore errorStore;
private MessageProcessor messageProcessor;
在獨立的方法中建立各物件:
@BeforeEach
void setUp() {
this.infoStore = mock(InfoStore.class);
this.errorStore = mock(errorStore.class);
this.messageProcessor = new MessageProcessor(infoStore, errorStore);
}
測試類別將變為:
@Test
void process_savesToInfoStore_whenInfoMessage() {
messageProcessor.process("[INFO] Process started.");
verify(infoStore).save("[INFO] Process started.");
verifyNoInteractions(errorStore);
}
整體流程:
class MessageProcessorTest { private InfoStore infoStore; // 宣告欄位@BeforeEach void setUp() { this.infoStore = mock(InfoStore.class); // 初始化欄位 }@Test void process_savesToInfoStore_whenInfoMessage() { // 使用欄位 } }
Java 測試入門