Java 測試入門
Maria Milusheva
Senior Software Engineer
回想上一課的相依流程:匯率換算 App 相依於銀行伺服器:

無法驗證計算,因為匯率本質上不可預測。
Mocking —— 為測試中難以使用的真實物件建立模擬物件或行為,讓你在不依賴外部相依的情況下進行測試。
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

回到上一課:
public double convertEuroTo(String currency, double amount) {
double rate = this.bank.getRateEuroTo(currency);
return amount * rate;
}
➡ 為測試建立可預期的 EuropeanCentralBankServer 物件
使用 mock 進行測試如下:
@Test void convert_returnsExpectedValue() { EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class); ExchangeApp exchangeApp = new ExchangeApp(bank);// 需要為 mock 設定行為 when(bank.getRateEuroTo("USD")).thenReturn(1.1);// 從 mock 物件呼叫 getRateEuroTo,取得預先設定的值 double result = exchangeApp.convertEuroTo("USD", 1000); assertEquals(1100, result); // 現在可對精確回傳值進行斷言 }
別忘了為 mock 設定行為:
@Test
void convert_returnsExpectedValue() {
EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
ExchangeApp exchangeApp = new ExchangeApp(bank);
// 未設定 mock 行為——mock 的 bank 物件不知道如何回應 getRateEuroTo
double result = exchangeApp.convertEuroTo("USD", 1000);
assertEquals(1100, result); // 由於未設定 mock,測試會失敗
}
測試失敗如下:
org.opentest4j.AssertionFailedError:
Expected :1100.0
Actual :0.0
為 mock 設定行為稱為stubbing。
Stubbing —— 在測試期間,對呼叫提供最小且預先定義的回應;對未設定的呼叫通常不回應。
Mockito 也能模擬錯誤情境:
EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
ExchangeApp exchangeApp = new ExchangeApp(bank);
// 改用 thenThrow() 取代 thenReturn()
when(bank.getRateEuroTo("USD"))
.thenThrow(new RuntimeException("Bank server unavailable."));
exchangeApp.convertEuroTo("USD", 1000); // getRateEuroTo 會拋出例外
Java 測試入門