← Назад к вопросам

Какой жизненный цикл Unit теста?

1.0 Junior🔥 201 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Жизненный цикл Unit теста в JUnit

Это фундаментальный вопрос о структуре и порядке выполнения Unit тестов. Понимание жизненного цикла критично для написания правильных тестов.

Основные этапы жизненного цикла

Для каждого тестового метода JUnit выполняет следующие этапы:

1. Инстанцирование класса теста
2. @BeforeClass (один раз для всего класса) — JUnit 4
3. Для каждого тестового метода:
   a) @Before (@BeforeEach в JUnit 5)
   b) @Test метод
   c) @After (@AfterEach в JUnit 5)
4. @AfterClass (один раз после всех тестов) — JUnit 4

JUnit 4 пример

import org.junit.BeforeClass;
import org.junit.Before;
import org.junit.Test;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;

public class CalculatorTest {
    private Calculator calculator;
    private static DatabaseConnection connection;
    
    // Выполняется один раз перед всеми тестами класса
    @BeforeClass
    public static void setUpBeforeClass() {
        System.out.println("1. @BeforeClass - инициализация общих ресурсов");
        connection = new DatabaseConnection();
        connection.connect();
    }
    
    // Выполняется перед каждым тестовым методом
    @Before
    public void setUp() {
        System.out.println("2. @Before - инициализация перед каждым тестом");
        calculator = new Calculator();
    }
    
    // Первый тест
    @Test
    public void testAdd() {
        System.out.println("3. @Test - выполнение первого теста");
        int result = calculator.add(2, 3);
        assertEquals(5, result);
    }
    
    // Выполняется после первого теста
    @After
    public void tearDown() {
        System.out.println("4. @After - очистка после первого теста");
        calculator = null;
    }
    
    // Второй тест
    @Test
    public void testSubtract() {
        System.out.println("3. @Test - выполнение второго теста");
        System.out.println("2. @Before - инициализация перед вторым тестом");
        int result = calculator.subtract(5, 3);
        assertEquals(2, result);
    }
    
    // Выполняется после второго теста
    // (снова @After)
    
    // Выполняется один раз после всех тестов
    @AfterClass
    public static void tearDownAfterClass() {
        System.out.println("5. @AfterClass - очистка общих ресурсов");
        connection.disconnect();
    }
}

Порядок вывода:

1. @BeforeClass - инициализация общих ресурсов
2. @Before - инициализация перед каждым тестом
3. @Test - выполнение первого теста
4. @After - очистка после первого теста
2. @Before - инициализация перед вторым тестом
3. @Test - выполнение второго теста
4. @After - очистка после второго теста
5. @AfterClass - очистка общих ресурсов

JUnit 5 пример (современный подход)

В JUnit 5 именование изменилось для большей ясности:

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.AfterAll;
import static org.junit.jupiter.api.Assertions.*;

public class CalculatorTest {
    private Calculator calculator;
    private static DatabaseConnection connection;
    
    // Один раз перед всеми тестами (статический метод)
    @BeforeAll
    public static void setUp() {
        System.out.println("@BeforeAll - один раз перед всеми тестами");
        connection = new DatabaseConnection();
        connection.connect();
    }
    
    // Перед каждым тестом (экземплярный метод)
    @BeforeEach
    public void setUpEach() {
        System.out.println("@BeforeEach - перед каждым тестом");
        calculator = new Calculator();
    }
    
    @Test
    public void testAdd() {
        System.out.println("@Test - выполнение теста");
        assertEquals(5, calculator.add(2, 3));
    }
    
    @Test
    public void testSubtract() {
        System.out.println("@Test - выполнение теста");
        assertEquals(2, calculator.subtract(5, 3));
    }
    
    // После каждого теста
    @AfterEach
    public void tearDownEach() {
        System.out.println("@AfterEach - после каждого теста");
        calculator = null;
    }
    
    // Один раз после всех тестов (статический метод)
    @AfterAll
    public static void tearDown() {
        System.out.println("@AfterAll - один раз после всех тестов");
        connection.disconnect();
    }
}

Соответствие между JUnit 4 и JUnit 5

JUnit 4JUnit 5Применяется
@BeforeClass@BeforeAllОдин раз, перед всеми тестами
@Before@BeforeEachПеред каждым тестом
@Test@TestТестовый метод
@After@AfterEachПосле каждого теста
@AfterClass@AfterAllОдин раз, после всех тестов

Практический пример: Database Connection

public class UserRepositoryTest {
    private static Database db;
    private UserRepository userRepository;
    
    @BeforeAll
    public static void initDatabase() {
        // Очень дорогая операция - подключение к БД
        // Выполняется один раз
        db = new Database();
        db.connect();
        db.migrateSchema();
    }
    
    @BeforeEach
    public void setup() {
        // Очищаем данные перед каждым тестом
        db.clearData();
        userRepository = new UserRepository(db);
    }
    
    @Test
    public void testCreateUser() {
        User user = userRepository.create("John");
        assertNotNull(user.getId());
    }
    
    @Test
    public void testFindUser() {
        userRepository.create("Jane");
        User found = userRepository.findByName("Jane");
        assertEquals("Jane", found.getName());
    }
    
    @AfterEach
    public void cleanup() {
        // Может быть дополнительная очистка
        userRepository = null;
    }
    
    @AfterAll
    public static void closeDatabase() {
        // Закрываем соединение один раз
        db.disconnect();
    }
}

Важные моменты

1. @BeforeClass / @BeforeAll ДОЛЖНЫ быть static

@BeforeAll
public static void staticSetup() {  // STATIC!
    // инициализация
}

2. @Before / @BeforeEach могут быть обычные методы

@BeforeEach
public void instanceSetup() {  // обычный метод
    calculator = new Calculator();
}

3. Исключения в @Before пропускают тест

@BeforeEach
public void setup() throws IOException {
    // Если здесь исключение, @Test не выполнится
    fileReader = new FileReader("data.txt");
}

4. @After выполняется ВСЕГДА, даже при ошибке

@AfterEach
public void cleanup() {
    // Выполнится даже если @Test упал!
    if (fileReader != null) {
        fileReader.close();  // гарантированная очистка
    }
}

Резюме

  • Жизненный цикл: инициализация → тест → очистка
  • @BeforeAll / @BeforeClass: один раз перед всеми (статический)
  • @BeforeEach / @Before: перед каждым тестом (экземплярный)
  • @Test: сам тест
  • @AfterEach / @After: после каждого теста (экземплярный)
  • @AfterAll / @AfterClass: один раз после всех (статический)
  • Используй этот цикл для инициализации и очистки ресурсов
  • JUnit 5 более современный и гибкий для сложных сценариев
Какой жизненный цикл Unit теста? | PrepBro