4.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")));
    }
}

4.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")));
        }
   }
}

Более подробно можно почитать в официальной документации.

4.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.4 @Timeout

Закончим эту лекцию небольшой и интересной аннотацией @Timeout. Она позволяет задать время на выполнение теста. Если выполнение теста заняло больше времени, чем указанно в аннотации, то он считается проваленным.


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

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