Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Tests Java: Веб-технологии

AppTest.java

class AppTest {

    private static Javalin app;
    private static String baseUrl;
    private static Transaction transaction;

    // Метод выполнится перед всеми тестами в классе
    @BeforeAll
    public static void beforeAll() {
        // Получаем инстанс приложения
        app = App.getApp();
        // Запускаем приложение на рандомном порту
        app.start(0);
        // Получаем порт, на которм запустилось приложение
        int port = app.port();
        // Формируем базовый URL
        baseUrl = "http://localhost:" + port;
    }

    // Метод выполнится после окончания всех тестов в классе
    @AfterAll
    public static void afterAll() {
        // Останавливаем приложение
        app.stop();
    }

    @Test
    void testSonething() {

        // Выполняем POST запрос при помощи агента Unirest
        HttpResponse<String> responsePost = Unirest
            // POST запрос на URL
            .post(baseUrl + "/companies")
            // Устанавливаем значения полей
            .field("name", "Google")
            .field("anotherField", "another value")
            // Выполняем запрос и получаем тело ответ с телом в виде строки
            .asString();

        // Проверяем статус ответа
        assertThat(responsePost.getStatus()).isEqualTo(302);

        // Проверяем, что компания добавлена в БД
        User actualCompany = new QCompany()
            .name.equalTo("Google")
            .findOne();

        assertThat(actualCompany).isNotNull();

        // И что её данные соответствуют переданным
        assertThat(actualUser.getName()).isEqualTo("Google");
        assertThat(actualUser.getAnotherField()).isEqualTo("another valeu");

        // Можно проверить, что такой компании нет в БД
        assertThat(actualCompany).isNull();

        // Так можно получить содержимое тела ответа
        String content = responsePost.getBody();

        // И проверить, что оно содержит определённую строку
        assertThat(content).contains("yandex.ru");
    }
}

При тестировании возникают такие ситуации, что нужно проверить работу метода, выполняющего HTTP-запрос. Предположим, что у нас есть метод App.getTitle(), который выполняет запрос на переданный url и анализирует данные полученной страницы. Например, получает заголовок этой страницы. Давайте его протестируем. Мы хотим убедиться, что метод работает правильно – анализирует полученную информацию и возвращает результат. Идеальный тест выглядел бы так:

class AppTest {

    @Test
    void testSomething() {
        var url = "http://example.com/";
        var title = App.getTitle(url);
        assertThat(title).isEqualTo("Example title");
    }
}

Но внутри метода App.getTitle() выполняется HTTP-запрос. Из-за этого могут возникнуть следующие проблемы:

  • Нестабильная сеть может тормозить выполнение тестов и приводить к "фантомным" ошибкам. Тесты будут иногда проходить, иногда нет.
  • У некоторых сервисов (например github.com), установлены ограничения на запросы в секунду, в час, день и так далее. Тесты начнут упираться в эти лимиты. Более того, есть шанс что машина с которой идут запросы, будет заблокирована.
  • Реальные данные на страницах не статичны, они могут и, скорее всего, будут меняться, что опять же приведет к ошибкам и необходимости править тесты.

В данном примере HTTP-запрос воспринимается как помеха к тому, чтобы протестировать нашу основную логику. Мы доверяем библиотеке, которая выполняет запросы внутри нашего метода App.getTitle(), нам не нужно проверять, что она работает правильно.

Чтобы выйти из этой ситуации, в Java есть библиотека MockWebServer, которая имитирует поведение реального удаленного сервера, но не выполняет реальные запросы через Интернет.

import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.MockResponse;

class AppTest {

    private static MockWebServer mockServer;

    @BeforeAll
    public static void beforeAll() {
        // Создаем новый экземпляр MockWebServer
        mockServer = new MockWebServer();

        // Создаём инстанс MockResponse, и устанавливаем нужное тело ответа
        // Это и есть та фейковая страница, а точнее её содержимое (html),
        // с которой будет работать наш метод в тестах
        MockResponse mockedResponse = new MockResponse()
            .setBody(readFixture("index.html"));

        // Добавляем инстанс MockResponse в очередь к созданному серверу
        mockServer.enqueue(mockedResponse);
        // Запускаем сервер
        mockServer.start();

    }

    @AfterAll
    public static void afterAll() {
        // После выполнения тестов нужно остановить сервер
        mockServer.shutdown();
    }

    @Test
    void testGetHeader() {
        // Вызвав на созданном инстансе сервера метод mockServer.url("/").toString(),
        // можно получить адрес сайта, который нужно будет использовать в тестах
        String url = mockServer.url("/").toString().replaceAll("/$", "");

        // Вызываем наш метод, передав ему полученный адрес
        // Метод выполнит запрос к нашей имитации реального сервера
        var title = App.getTitle(url);
        assertThat(title).isEqualTo("Example title");
    }
}

Содержимое фейковой страницы. Файл index.html

<html lang='en'>
    <head>
        <title>Example title</title>
    </head>
    <body>
        <div>
            <h1>Test page</h1>
        </div>
    </body>
</html>

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Java-разработчик
Профессия
с нуля
Разработка приложений на языке Java
2 февраля 10 месяцев

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу