Giả lập (Mock) và Stubbing trong kiểm thử đơn vị

Nhập môn Kiểm thử trong Java

Maria Milusheva

Senior Software Engineer

Động lực: Phụ thuộc

Nhớ lại luồng phụ thuộc ở bài trước: Ứng dụng đổi tiền tệ phụ thuộc vào máy chủ ngân hàng: Biểu đồ Mermaid về luồng phụ thuộc trong demo ngân hàng

Không thể xác minh phép tính vì tỷ giá hối đoái vốn dĩ không thể dự đoán.

Nhập môn Kiểm thử trong Java

Quản lý phụ thuộc trong kiểm thử

Mocking - tạo đối tượng/hành vi mô phỏng cho các đối tượng khó dùng trong kiểm thử, giúp kiểm thử mà không phụ thuộc vào hệ thống bên ngoài.


import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

Ví dụ về mocking

Nhập môn Kiểm thử trong Java

Mocking

  • Mock = như diễn viên đóng thế, chỉ giả làm đối tượng thật trong phạm vi bài test

Xét bài trước:

public double convertEuroTo(String currency, double amount) {
    double rate = this.bank.getRateEuroTo(currency);
    return amount * rate;
}

➡ Tạo đối tượng có thể dự đoán cho EuropeanCentralBankServer để kiểm thử

Nhập môn Kiểm thử trong Java

Mocking: Đổi tiền tệ

Cách kiểm thử với mock:

@Test
void convert_returnsExpectedValue() {
    EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
    ExchangeApp exchangeApp = new ExchangeApp(bank);

// Cần lập trình cho mock để hoạt động when(bank.getRateEuroTo("USD")).thenReturn(1.1);
// Gọi getRateEuroTo từ mock, nhận giá trị đã định sẵn double result = exchangeApp.convertEuroTo("USD", 1000); assertEquals(1100, result); // Giờ có thể assert giá trị chính xác }
Nhập môn Kiểm thử trong Java

Lỗi thường gặp

Không bao giờ quên lập trình cho mock:

@Test
void convert_returnsExpectedValue() {
    EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
    ExchangeApp exchangeApp = new ExchangeApp(bank);

    // Không lập trình mock - mock bank không biết phản hồi getRateEuroTo
    double result = exchangeApp.convertEuroTo("USD", 1000);

    assertEquals(1100, result); // Sẽ fail do thiếu thiết lập mock
}
Nhập môn Kiểm thử trong Java

Stubbing

Bài kiểm thử thất bại với:

org.opentest4j.AssertionFailedError: 
Expected :1100.0
Actual   :0.0

Lập trình hành vi cho mock gọi là stubbing.

Stubbing - cung cấp câu trả lời tối thiểu, định sẵn cho các lệnh gọi trong bài test, và thường không phản hồi ngoài những gì đã lập trình cho bài test.

Nhập môn Kiểm thử trong Java

Ngoại lệ với Mockito

Mockito cũng có thể mô phỏng kịch bản lỗi:

EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
ExchangeApp exchangeApp = new ExchangeApp(bank);
// Thay vì thenReturn() dùng thenThrow()
when(bank.getRateEuroTo("USD"))
        .thenThrow(new RuntimeException("Bank server unavailable."));

exchangeApp.convertEuroTo("USD", 1000); // getRateEuroTo sẽ ném ngoại lệ
Nhập môn Kiểm thử trong Java

Ayo berlatih!

Nhập môn Kiểm thử trong Java

Preparing Video For Download...