← Назад к вопросам

Зачем мокать запросы?

1.7 Middle🔥 121 комментариев
#Теория тестирования#Фреймворки тестирования

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Зачем мокать запросы в тестировании

В контексте автоматизированного тестирования, особенно для QA Automation, мокирование запросов (или Mocking) — это фундаментальная практика, направленная на создание контролируемых, изолированных и надежных тестовых условий. Основная цель — замена реальных внешних зависимостей (например, API, сервисов, баз данных) на их искусственные, программируемые версии во время выполнения тестов.

Ключевые причины и преимущества мокирования запросов

  • Изоляция тестируемого компонента (Unit Testing). Когда мы тестируем конкретный модуль, класс или функцию (например, сервис, который обращается к внешнему API), мы хотим оценить его логику в чистом виде, без влияния "внешнего мира". Мок позволяет "отключить" реальный сервер и проверить, правильно ли наш код формирует запрос, обрабатывает ответ или реагирует на ошибки.
  • Контроль над тестовым окружением. Реальный сервер может быть недоступен, медленным, возвращать разные данные в разное время или иметь ограничения на частоту запросов. Мок дает полный контроль:
    *   Мы можем гарантировать, что тест всегда получает **предопределенный ответ** (успешный, с ошибкой 404, 500, etc.).
    *   Мы можем **симулировать любые сценарии**: медленный ответ (timeout), нестандартные данные, изменение контракта API.
    *   Тесты становятся **быстрыми** и **стабильными**, так как не зависят от сетевой latency или доступности сторонних систем.
  • Тестирование негативных и граничных сценариев. С реальным API сложно (или невозможно) добиться конкретной ошибки, например, "сервер вернул 503 ошибку в третьем запросе". Мок позволяет легко моделировать такие ситуации для проверки устойчивости (resilience) и корректности обработки ошибок в нашем приложении.
  • Экономия ресурсов и безопасность. Тесты не выполняют реальные операции, которые могут стоить денег (платные API), изменять производственные данные или создавать нагрузку на реальные системы. Мокирование исключает эти риски.
  • Раннее тестирование и разработка. Если внешний сервис еще не готов, мы можем создать его мок-версию, основанную на согласованном контракте (Swagger/OpenAPI), и начать интеграцию и тестирование нашего кода сразу. Это поддерживает подход Contract Testing.

Типичные сценарии применения

  1. Тестирование клиента API. Например, класс UserApiClient, метод getUser(id).
    # Пример с использованием библиотеки pytest-mock
    def test_get_user_handles_404(mocker):
        # Мокаем метод, который выполняет HTTP-запрос
        mock_request = mocker.patch('modules.http_client.send_request')
        # Настраиваем мок на возвращение ответа с ошибкой 404
        mock_request.return_value = MockResponse(status_code=404, text='Not Found')
    
        api_client = UserApiClient()
        result = api_client.get_user(123)
    
        # Проверяем, что наш клиент корректно обработал ошибку
        assert result is None
        # Проверяем, что запрос был вызван с ожидаемыми параметрами
        mock_request.assert_called_once_with('https://api.example.com/users/123')
    
  2. Интеграционные тесты без реальной зависимости. Тест бизнес-логики, которая использует несколько сервисов.
    // Пример в JavaScript с использованием Jest
    test('Order processing calculates total correctly', async () => {
        // Мокаем внешний сервис цен
        const mockPriceService = jest.mock('./priceService');
        mockPriceService.getPrice.mockResolvedValue(100);
    
        // Мокаем сервис скидок
        const mockDiscountService = jest.mock('./discountService');
        mockDiscountService.getDiscount.mockResolvedValue(0.1);
    
        const orderProcessor = new OrderProcessor();
        const total = await orderProcessor.processOrder({ items: 2 });
    
        // Тест проверяет только вычисления, не реальные запросы к API
        expect(total).toBe(180); // 2 * 100 * (1 - 0.1)
    });
    
  3. Симуляция состояний сторонней системы. Например, тестирование кода, который должен повторять запрос при временной ошибке.
    def test_api_client_retries_on_timeout(mocker):
        mock_request = mocker.patch('modules.http_client.send_request')
        # Настраиваем мок: первые два вызова — timeout, третий — успешный
        mock_request.side_effect = [TimeoutError, TimeoutError, MockResponse(data='OK')]
    
        client = ApiClient(retries=3)
        result = client.fetch_data()
    
        assert result == 'OK'
        assert mock_request.call_count == 3  # Проверяем, что retry логика работала
    

Что важно помнить

  • Моки — не полноценная замена интеграционных тестов. После мокирования отдельных модулей необходимо выполнить интеграционные или end-to-end тесты с реальными (или близкими к реальным) сервисами в контролируемом, но приближенном к production окружении (например, staging environment). Это проверяет реальную совместимость.
  • Мок должен отражать реальный контракт. Если реальный API меняет формат ответа, мок должен быть обновлен. Здесь помогают практики Contract Testing (например, с Pact).
  • Избегайте over-mocking. Не стоит мокать всё; чрезмерное мокирование может создать тесты, которые проверяют лишь взаимодействие с моками, а не реальную бизнес-логику.

Итог: Мокирование запросов — это мощный инструмент для создания быстрых, стабильных, контролируемых и всеобъемлющих автоматических тестов. Оно позволяет сосредоточиться на поведении тестируемого кода, минимизировать внешние риски и проводить тестирование на ранних этапах разработки, что в итоге повышает качество продукта и эффективность процесса разработки.

Зачем мокать запросы? | PrepBro