JavaRush /Курсы /JSP & Servlets /Настройка окружения теста в JUnit

Настройка окружения теста в JUnit

JSP & Servlets
3 уровень , 2 лекция
Открыта

3.1 Аннотации @BeforeEach, @AfterEach

Обрати внимание, что в предыдущем примере нам в каждом методе приходилось писать код для создания объекта Calculator.

Конечно, это всего одна строчка, но если мы будем тестировать реальные системы, то часто будет возникать ситуация, когда нужно создать и сконфигурировать несколько объектов, что может занять несколько десятков строк кода. Пример:


   //Создаем объект HttpClient
   HttpClient client = HttpClient.newBuilder()
    	.version(Version.HTTP_1_1)
    	.followRedirects(Redirect.NORMAL)
        .connectTimeout(Duration.ofSeconds(20))
    	.proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
        .authenticator(Authenticator.getDefault())
    	.build();
 
   //Создаем объект HttpRequest
  HttpRequest request = HttpRequest.newBuilder()
     .uri(new URI("https://javarush.com"))
     .headers("Content-Type", " application/octet-stream")
     .POST( HttpRequest.BodyPublishers. ofInputStream ( () -> is; ))
     .build();
 
   //Вызываем метод send()
   HttpResponse
      
  
      
  
      
  
    response = client.send(request, BodyHandlers.ofString()); System.out.println(response.statusCode()); System.out.println(response.body()); 
  

В примере выше мы создали и сконфигурировали объект HttpClient и хотим протестировать работу метода send().

Чтобы каждый раз в тестовом методе не писать создание объекта HttpClient, его можно вынести в отдельный метод и поставить ему специальную аннотацию @BeforeEach. Тогда Junit будет вызывать этот метод перед каждым тестовым методом. Пример:


    class HttpClientTest {
     	public HttpClient client;
 
   	@BeforeEach
    	public void init(){
   	   client = HttpClient.newBuilder()
   	        .version(Version.HTTP_1_1)
   	        .followRedirects(Redirect.NORMAL)
   	        .connectTimeout(Duration.ofSeconds(20))
   	        .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
   	        .authenticator(Authenticator.getDefault())
   	        .build();
    	}
 
   	@Test
    	public void send200() throws Exception {
     	   //Создаем объект HttpRequst()
         	HttpRequest request = HttpRequest.newBuilder(new URI("https://javarush.com")).build();
 
     	   //Вызываем метод send()
     	   HttpResponse
      
  
      
  
      
  
    response = client.send(request, BodyHandlers.ofString()); assertEquals(200, response.statusCode()); } @Test public void send404() throws Exception { //Создаем объект HttpRequst() HttpRequest request = HttpRequest.newBuilder(new URI("https://javarush.com/unknown")).build(); //Вызываем метод send() HttpResponse 
   
     response = client.send(request, BodyHandlers.ofString()); assertEquals(404, response.statusCode()); } } 
    
  

Также можно создать специальный метод, который будет вызываться каждый раз после очередного тестового метода, и подчищать использованные ресурсы, писать что-то в лог и т. п. Такой метод нужно пометить аннотацией @AfterEach.

Если у тебя есть 3 тестовых метода test1(), test2() и test3(), то порядок вызова будет таким:

  • BeforeEach-метод
  • test1()
  • AfterEach-метод
  • BeforeEach-метод
  • test2()
  • AfterEach-метод
  • BeforeEach-метод
  • test3()
  • AfterEach-метод

3.2 Аннотации @BeforeAll, @AfterAll

JUnit также позволяет добавить метод, который будет вызван один раз перед всеми тестовыми методами. Такой метод нужно пометить аннотацией @BeforeAll. Для нее так же существует парная аннотация @AfterAll. Метод, помеченный ею, JUnit вызовет после всех тестовых методов.

Давай напишем специальный пример, который позволяет лучше понять, как это все работает. За основу возьмем тестирование нашего калькулятора:


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

    @BeforeAll
    public static void init(){
        System.out.println("BeforeAll init() method called");
    }
 
    @BeforeEach
    public void initEach(){
        System.out.println("BeforeEach initEach() method called");
    }
 
    @Test
    public void add(){
        System.out.println("Testing Addition");
    }
 
    @Test
    public void sub() {
        System.out.println("Testing Subtraction");
    }
 
    @Test
    public void mul(){
        System.out.println("Testing Multiplication");
    }
 
    @Test
    public void div() {
        System.out.println("Testing Division");
    }
}

Этот тест напечатает в консоль такой текст:


BeforeAll init() method called
BeforeEach initEach() method called
Testing Addition
 
BeforeEach initEach() method called
Testing Subtraction
 
BeforeEach initEach() method called
Testing Multiplication
 
BeforeEach initEach() method called
Testing Division
Комментарии (7)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Denis Odesskiy Уровень 47
18 августа 2025
Чтобы работал тест с калькулятором и @BeforeEach, например, создайте приватное поле типа Calculator, затем проинициализируйте его в методе помеченной аннотацией @BeforeEach, и уберите создание экземпляров класса из @Test, теперь они там лишние. А то, как показано в этой лекции непонятно, что вызвать в @BeforeEach, чтобы тесты калькулятора работали.

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

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

class CalculatorTest {
    private Calculator calc;
    @BeforeEach
    public void initEach() {
        calc = new Calculator();
    }

    @Test
    public void add() {
        int result = calc.add(2, 3);
        assertEquals(5, result);
    }

    @Test
    public void sub() {
        int result = calc.sub(10, 10);
        assertEquals(0, result);
    }

    @Test
    public void mul() {
        int result = calc.mul(-5, -3);
        assertEquals(15, result);
    }

    @Test
    public void div() {
        int result = calc.div(2, 3);
        assertEquals(0, result);
    }
}
Рустам Уровень 115
8 марта 2025
Оформление кода - пушка
Андрей Уровень 37 Expert
18 июля 2024
Если кто-то захочет запустить HttpClientTest и у него проблема с Authenticator.getDefault() - NPE то иницилизируйте по другому:

 @BeforeEach
    public void init(){
            client = HttpClient.newHttpClient();
    }
или закоментируйте эти строки

 public void init(){
        client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .followRedirects(HttpClient.Redirect.NORMAL)
                .connectTimeout(Duration.ofSeconds(20))
//                .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
//                .authenticator(Authenticator.getDefault())
                .build();
    }

или настройте реальный прокси....
Павел Уровень 19 Expert
14 декабря 2023
Хорошо было бы сначала познакомиться заранее где-нибудь в лекциях с HttpClient, HttpRequest, а потом использовать эти классы в примерах.
eldar516 Уровень 100
19 июня 2022
на 4 и 5 junit методы аннотированные BeforeAll и AfterAll выбрасывают JUnitException, если не аннотировать класс @TestInstance(TestInstance.Lifecycle.PER_CLASS)
Ramz Уровень 35
8 июля 2022
Либо static
Zhenya Workout Уровень 43
26 августа 2023
Методы помеченные данными аннотациями должны быть статичными.