Следует ли разбивать тестирование одного метода на несколько отдельных unit-тестов?

«Следует ли разбивать тестирование одного метода на несколько отдельных unit-тестов?» — вопрос из категории Тестирование, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, это основополагающий принцип модульного тестирования (FIRST принцип). Каждый тест должен проверять одну конкретную ответственность или сценарий (Single Responsibility Principle для тестов).

Преимущества такого подхода:

  • Ясность: Название теста (testWithdraw_WithInsufficientBalance_ThrowsException) точно описывает проверяемый сценарий.
  • Изоляция: Падение одного теста локализует проблему до конкретного условия.
  • Поддержка: Легче добавлять новые сценарии и рефакторить код тестов.
  • Документация: Набор тестов служит живой документацией поведения метода.

Пример (тестирование метода Calculator.add(int a, int b)):

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    private final Calculator calc = new Calculator();

    @Test
    void add_TwoPositiveNumbers_ReturnsCorrectSum() {
        assertEquals(5, calc.add(2, 3));
    }

    @Test
    void add_PositiveAndNegativeNumbers_ReturnsCorrectSum() {
        assertEquals(-1, calc.add(2, -3));
    }

    @Test
    void add_WithZero_ReturnsOtherOperand() {
        assertEquals(2, calc.add(2, 0));
        assertEquals(2, calc.add(0, 2));
    }

    @Test
    void add_MaxIntOverflow_ThrowsArithmeticException() {
        assertThrows(ArithmeticException.class, () -> calc.add(Integer.MAX_VALUE, 1));
    }
}

Практическое правило: Если в тесте появляется логический оператор && ("и") в утверждении (assert) или его название содержит "and", это сигнал, что тест лучше разбить на два.