Мокирование и стабирование в юнит-тестах

Введение в тестирование на Java

Maria Milusheva

Senior Software Engineer

Мотивация: зависимости

Вспомним поток зависимостей из предыдущего урока: приложение обмена валют зависит от банковского сервера: Граф зависимостей банковского демо-приложения в Mermaid

Проверить вычисления невозможно, так как курсы валют по своей природе непредсказуемы.

Введение в тестирование на Java

Управление зависимостями в тестировании

Мокирование — создание имитаций объектов или поведений вместо реальных объектов, которые сложно использовать в тестах. Позволяет тестировать код без обращения к внешним зависимостям.


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

Пример мокирования

Введение в тестирование на Java

Мокирование

  • Мок — как дублёр в спектакле: подменяет реальный объект ровно настолько, насколько это нужно тесту

Вернёмся к предыдущему уроку:

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

➡ Создайте предсказуемый объект для EuropeanCentralBankServer в целях тестирования

Введение в тестирование на Java

Мокирование: обмен валют

Вот как выглядит тестирование с моками:

@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 }
Введение в тестирование на Java

Распространённая ошибка

Не забывайте программировать моки:

@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
}
Введение в тестирование на Java

Стабирование

Тест завершается с ошибкой:

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

Программирование мока называется стабированием.

Стабирование — предоставление заранее определённых ответов на вызовы, выполняемые в ходе теста. Как правило, мок не реагирует ни на что, кроме запрограммированных сценариев.

Введение в тестирование на Java

Исключения в Mockito

Mockito также позволяет имитировать сценарии с ошибками:

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
Введение в тестирование на Java

Давайте потренируемся!

Введение в тестирование на Java

Preparing Video For Download...