1. @Disabled

Тепер розберемо кілька дуже корисних та популярних анотацій фреймворку JUnit. Перша анотація дозволяє вимкнути певний тест, щоб JUnit його не викликав. Вона потрібна в разі якщо ти помітиш, що тест працює неправильно, або зміниш код і тест випадково зламається.

Як ми вже говорили, 99% тестів ніхто не підтримує, тому їх всіх рано чи пізно вимикають. Тому ця анотація перша у списку корисних.

Розглянемо її на прикладі:


public class AppTest {

    @Disabled("Тест тимчасово вимкнено. Правда, правда")
    @Test
    void testOnDev(){
        System.setProperty("ENV", "DEV");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
    }

    @Test
    void testOnProd(){
     System.setProperty("ENV", "PROD");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
    }
}

У прикладі вище метод testOnDev() не буде викликатися. До речі, анотацію @Disabled можна написати одразу перед оголошенням класу: в цьому разі всі його методи проігноруються.


@Disabled("Тимчасово вимкнули тест, полагодимо його до травня 2001 року")
public class AppTest {
    @Test
    void testOnDev(){
        System.setProperty("ENV", "DEV");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
    }

    @Test
    void testOnProd(){
     System.setProperty("ENV", "PROD");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
    }
}

2. @Nested

JUnit дозволяє викликати тестові методи вкладених класів. Маються на увазі вкладені тестові класи. Не факт, що ти часто стикатимешся з ними, але ймовірність така є, тому потрібно розуміти, що це таке.

Щоб викликати методи вкладеного класу перед його оголошенням, потрібно написати анотацію @Nested. Приклад:


public class AppTest {
    @Nested
    public class DevStagingEnvironment {
    @Test
        void testOnDev(){
            System.setProperty("ENV", "DEV");
            Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
        }
   }

    @Nested
    public class ProductionEnvironment {
        @Test
        void testOnProd(){
           System.setProperty("ENV", "PROD");
           Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
        }
   }
}

Докладніше про це можна почитати в офіційній документації.

3. @ExtendWith

Інша корисна інструкція – @ExtendWith. Швидше за все ти зустрічатимеш її дуже часто, тож розглянемо її докладніше.

JUnit – це потужний фреймворк, який дозволяє писати різні плагіни (розширення) для гнучкого налаштування своєї роботи. Деякі розширення можуть збирати статистику про тести, інші – емулювати файлову систему в пам'яті, інші – емулювати роботу всередині вебсервера тощо.

Якщо твій код працює всередині якогось фреймворку (наприклад Spring), майже завжди цей фреймворк керує створенням та налаштуванням об'єктів твого коду. Тому без спеціального тестового плагіна не обійтися. Приклади:

Приклад 1. Розширення WebServerExtension передає до тестового методу, що викликається, URL для коректної роботи.


@Test
@ExtendWith(WebServerExtension.class)
void getProductList(@WebServerUrl String serverUrl) {
    WebClient webClient = new WebClient();
    // Use WebClient to connect to web server using serverUrl and verify response
    assertEquals(200, webClient.get(serverUrl + "/products").getResponseStatus());
}

Ось так зазвичай починаються тести для перевірки коду, який працює з фреймворком Spring:


@ExtendWith(SpringExtension.class)
@ExtendWith(MockitoExtension.class)
class TestServiceTest {

    @MockBean
    TestService service;

    @Test
    void test() {
        assertNotNull(service); // Test succeeds
    }
}

SpringExtension створює тестовий варіант фреймворку Spring, а MockitoExtention дозволяє створювати фейкові об'єкти. Фейкові об'єкти — тема дуже цікава, ми обов'язково її торкнемося, але трохи пізніше.

4. @Timeout

Закінчимо цю лекцію невеликою та цікавою анотацією @Timeout. Вона дозволяє встановити час виконання тесту. Якщо виконання тесту зайняло більше часу, ніж вказано в анотації, він вважається проваленим.


class TimeoutDemo {
    @Test
    @Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
    void failsIfExecutionTimeExceeds100Milliseconds() {
        // тест впаде, якщо займає більш ніж 100 милісекунд
    }
}

На цьому закінчимо нашу лекцію.