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<String> 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 {
     	   //Створюємо об'єкт HttpRequest()
         	HttpRequest request = HttpRequest.newBuilder(new URI("https://javarush.com")).build();

     	   //Викликаємо метод send()
     	   HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
        	assertEquals(200, response.statusCode());
        }

   	@Test
    	public void send404() throws Exception {
     	   //Створюємо об'єкт HttpRequest()
         	HttpRequest request = HttpRequest.newBuilder(new URI("https://javarush.com/unknown")).build();

     	   //Викликаємо метод send()
     	   HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
        	assertEquals(404, response.statusCode());
    	}
}

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

Якщо в тебе є 3 тестові методи test1(), test2() і test3(), порядок виклику буде таким:

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

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