Mockowanie i stubbing w testach jednostkowych

Wprowadzenie do testowania w Javie

Maria Milusheva

Senior Software Engineer

Motywacja: zależności

Przypomnijmy przepływ zależności z poprzedniej lekcji: aplikacja wymiany walut zależy od serwera bankowego: Graf Mermaid przedstawiający przepływ zależności w demo bankowym

Weryfikacja obliczeń jest niemożliwa, ponieważ kursy walut są z natury nieprzewidywalne.

Wprowadzenie do testowania w Javie

Zarządzanie zależnościami w testach

Mockowanie – tworzenie symulowanych obiektów lub zachowań w miejsce rzeczywistych, które są trudne do użycia w testach; pozwala testować bez polegania na zewnętrznych zależnościach.


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

Przykład mockowania

Wprowadzenie do testowania w Javie

Mockowanie

  • Mock = jak dubler w filmie – udaje prawdziwy obiekt wyłącznie na potrzeby testu

Odwołajmy się do poprzedniej lekcji:

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

➡ Utwórzmy przewidywalny obiekt dla EuropeanCentralBankServer na potrzeby testów

Wprowadzenie do testowania w Javie

Mockowanie: wymiana walut

Tak wygląda testowanie z użyciem mocków:

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

// Need to program the mock so it works when(bank.getRateEuroTo("USD")).thenReturn(1.1);
// Calls getRateEuroTo from the mock object, obtaining our pre-programmed values double result = exchangeApp.convertEuroTo("USD", 1000); assertEquals(1100, result); // We can now assert on exact return values }
Wprowadzenie do testowania w Javie

Częsty błąd

Nie wolno zapominać o zaprogramowaniu mocków:

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

    // No mock programming - mock bank object doesn't know how to respond to getRateEuroTo
    double result = exchangeApp.convertEuroTo("USD", 1000);

    assertEquals(1100, result); // Will fail due to lack of mock setup
}
Wprowadzenie do testowania w Javie

Stubbing

Test kończy się błędem:

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

Programowanie mocka nazywamy stubbingiem.

Stubbing – dostarczanie minimalnych, z góry zdefiniowanych odpowiedzi na wywołania wykonywane podczas testu, zazwyczaj bez reagowania na cokolwiek spoza tego, co zostało zaprogramowane.

Wprowadzenie do testowania w Javie

Wyjątki w Mockito

Mockito może również symulować scenariusze błędów:

EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
ExchangeApp exchangeApp = new ExchangeApp(bank);
// Instead of thenReturn() use thenThrow()
when(bank.getRateEuroTo("USD"))
        .thenThrow(new RuntimeException("Bank server unavailable."));

exchangeApp.convertEuroTo("USD", 1000); // getRateEuroTo will throw exception
Wprowadzenie do testowania w Javie

Czas na ćwiczenia!

Wprowadzenie do testowania w Javie

Preparing Video For Download...