JavaRush /Курсы /JSP & Servlets /Полезные аннотации в JUnit

Полезные аннотации в JUnit

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

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 миллисекунд
    }
}

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

Комментарии (13)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Андрей Уровень 37 Expert
26 июля 2024
Для @ExtendWith, пример 1 - создал необходимые классы, для понимания...

@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith({WebServerExtension.class})
public @interface WebServerUrl {
}

public class WebServerExtension implements ParameterResolver {
    @Override
    public boolean supportsParameter(ParameterContext pc, ExtensionContext extensionContext) throws ParameterResolutionException {
        return pc.isAnnotated(WebServerUrl.class);
    }

    @Override
    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
        return "https://javarush.com";
    }
Ну и можно протестировать getProductList. Только замените WebClient на HttpClient
Volodymyr Horbachev Уровень 63 Expert
29 сентября 2023
@ExtendWith Очень подробно рассмотрели...
23 января 2023
Можно написать

@Timeout(количество секунд)
и всё прекрасно будет работать.
Kirill Gerbliuk Уровень 27
23 января 2024
Работать будет. так как по стандарту, если не указывать unit - автоматически применится счисление в секундах. В случае если вы хотите таймаут поставить 30 миллисекунд, для этого вам необходимо вторым аргументом передать формат счисления, как и указано в примере, в ином случае ваши ожидания и execution вашего кода не будут сходится и вы будете гореть на джаву.
Inna Lapina Уровень 1
11 ноября 2022
"99% тестов никто не поддерживает, поэтому все они рано или поздно оказываются отключены" - это полная неправда, если у вас такой опыт, это еще не значит, что везде так. По-хорошему, на проекте должно быть покрыто тестами минимум 80% кода и при любых изменениях тесты переписываются или добавляются для нового кода.
Роман Уровень 115
7 октября 2025
приколист?
Сергей Уровень 22
17 июня 2022
@Timeout не работает. Если верно показывает IDE - то тест выполняется явно дольше чем указанное в аннотации. Почему так?
Stas S Уровень 108 Expert
2 сентября 2022
попробуй через Maven запустить фазу тестов ;) Еще как вариант Thread.sleep , на моем старом ноуте срабатывает даже с чуть меньшим значением, чем указано в тайм-ауте.
Musa Muradzade Уровень 1
17 июня 2022
@Disabled для всего класса не работает ... мб кто сталкивался с подобной проблемой?
Сергей Уровень 22
17 июня 2022
У меня работает 🤨
Musa Muradzade Уровень 1
17 июня 2022
А Вы не могли бы pom файл скинуть?
Сергей Уровень 22
18 июня 2022
Скинул в приват
Pavlo Plynko Уровень 40 Expert
22 июля 2022
Если запускать напрямую отключенный тест, то он выполнится. А если запускать много тестовых классов сразу, например все в директории, то тестовый класс должно пропустить.