Тестирование API запросов

API-тестирование является важной частью процесса разработки приложений, так как оно помогает убедиться, что сервер правильно обрабатывает запросы и отвечает на них с ожидаемыми данными. Jest, как популярный инструмент для тестирования JavaScript, предоставляет мощные возможности для тестирования API. В этой главе рассмотрены принципы и подходы к тестированию API-запросов с использованием Jest.

Настройка окружения для тестирования API

Для тестирования API с помощью Jest необходимо настроить несколько вещей. Обычно это включает в себя установку необходимых библиотек и настройку самого Jest для работы с HTTP-запросами.

  1. Установка зависимостей Чтобы тестировать API, необходимо установить Jest, а также дополнительные библиотеки для работы с HTTP-запросами, такие как axios или node-fetch. Например, для установки через npm можно выполнить следующую команду:

    npm install --save-dev jest axios
  2. Настройка Jest В файле конфигурации Jest (jest.config.js) можно указать различные параметры, такие как тайм-ауты для тестов и другие настройки:

    module.exports = {
      testTimeout: 10000, // Увеличение тайм-аута для API запросов
      // другие параметры конфигурации
    };

Написание простого теста API

Для начала рассмотрим пример тестирования простого GET-запроса. Допустим, у нас есть API, который возвращает список пользователей.

// Пользовательский сервис (например, src/userService.js)
import axios from 'axios';

export const getUsers = async () => {
  const response = await axios.get('https://jsonplaceholder.typicode.com/users');
  return response.data;
};

Теперь создадим тест для этой функции с использованием Jest.

// Тест для userService (например, src/userService.test.js)
import { getUsers } from './userService';
import axios from 'axios';

jest.mock('axios');  // Мокаем axios

describe('getUsers', () => {
  it('должен возвращать список пользователей', async () => {
    // Заготовка мока
    const users = [{ id: 1, name: 'John Doe' }];
    axios.get.mockResolvedValue({ data: users });

    const result = await getUsers();

    expect(result).toEqual(users);
  });

  it('должен выбросить ошибку, если запрос не удался', async () => {
    axios.get.mockRejectedValue(new Error('Network Error'));

    await expect(getUsers()).rejects.toThrow('Network Error');
  });
});

В этом примере:

  • Используется jest.mock() для создания мока библиотеки axios. Это позволяет имитировать поведение HTTP-запросов, не отправляя реальные запросы.
  • Метод mockResolvedValue() позволяет задать успешный результат запроса, а mockRejectedValue() — ошибку, которую должен выбросить запрос.

Тестирование API с использованием асинхронных запросов

API часто работает с асинхронными операциями, и важно правильно тестировать такие запросы. Jest поддерживает асинхронные тесты с использованием async/await, что позволяет тестировать работу API синхронным способом.

Пример тестирования асинхронного POST-запроса:

// Пример POST запроса
import axios from 'axios';

export const createUser = async (user) => {
  const response = await axios.post('https://jsonplaceholder.typicode.com/users', user);
  return response.data;
};

Тестирование этого запроса:

import { createUser } from './userService';
import axios from 'axios';

jest.mock('axios');

describe('createUser', () => {
  it('должен создавать нового пользователя', async () => {
    const newUser = { name: 'Jane Doe' };
    const createdUser = { id: 1, name: 'Jane Doe' };

    axios.post.mockResolvedValue({ data: createdUser });

    const result = await createUser(newUser);

    expect(result).toEqual(createdUser);
  });

  it('должен выбросить ошибку при неудачном запросе', async () => {
    const newUser = { name: 'Jane Doe' };

    axios.post.mockRejectedValue(new Error('Network Error'));

    await expect(createUser(newUser)).rejects.toThrow('Network Error');
  });
});

Этот пример также использует моки для симуляции поведения API, но уже для метода POST. Также показано, как можно проверять ошибки при неудачных запросах.

Мокирование данных и создание фейковых ответов

Иногда бывает полезно мокировать данные с использованием специальных фейковых серверов, таких как msw (Mock Service Worker). Это позволяет более гибко работать с запросами, не завися от реальных серверов.

Пример интеграции с msw:

npm install msw --save-dev
// Пример использования msw
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { getUsers } from './userService';

const server = setupServer(
  rest.get('https://jsonplaceholder.typicode.com/users', (req, res, ctx) => {
    return res(ctx.json([{ id: 1, name: 'John Doe' }]));
  })
);

// Настройка перед и после тестов
beforeAll(() => server.listen());
afterAll(() => server.close());
afterEach(() => server.resetHandlers());

describe('getUsers', () => {
  it('должен возвращать список пользователей', async () => {
    const result = await getUsers();
    expect(result).toEqual([{ id: 1, name: 'John Doe' }]);
  });
});

В этом примере используется библиотека msw для перехвата HTTP-запросов и возврата фейковых ответов. Это позволяет эмулировать поведение API и тестировать функциональность без необходимости в реальном сервере.

Проверка статус-кодов и заголовков

Для более глубокой проверки работы API важно также проверять не только данные в ответе, но и статус-коды HTTP и заголовки.

Пример:

import { getUsers } from './userService';
import axios from 'axios';

jest.mock('axios');

describe('getUsers', () => {
  it('должен возвращать статус 200 и данные пользователей', async () => {
    const users = [{ id: 1, name: 'John Doe' }];
    axios.get.mockResolvedValue({
      status: 200,
      data: users,
      headers: { 'content-type': 'application/json' }
    });

    const result = await getUsers();

    expect(result).toEqual(users);
    expect(axios.get).toHaveBeenCalledWith('https://jsonplaceholder.typicode.com/users');
  });

  it('должен проверять заголовки ответа', async () => {
    const response = {
      status: 200,
      data: [{ id: 1, name: 'John Doe' }],
      headers: { 'content-type': 'application/json' }
    };

    axios.get.mockResolvedValue(response);

    const result = await getUsers();
    
    expect(result).toEqual(response.data);
    expect(response.headers['content-type']).toBe('application/json');
  });
});

Здесь проверяется не только правильность данных, но и проверка правильности заголовков ответа и статус-кода.

Параллельные и комплексные запросы

В реальных приложениях API-запросы могут быть связаны и зависят друг от друга. В таких случаях полезно тестировать сценарии, где несколько запросов выполняются параллельно или последовательно.

Пример параллельных запросов:

import axios from 'axios';

export const fetchUserData = async (userId) => {
  const userResponse = await axios.get(`https://jsonplaceholder.typicode.com/users/${userId}`);
  const postsResponse = await axios.get(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`);
  
  return { user: userResponse.data, posts: postsResponse.data };
};

Тестирование:

import { fetchUserData } from './userService';
import axios from 'axios';

jest.mock('axios');

describe('fetchUserData', () => {
  it('должен загружать данные о пользователе и его постах', async () => {
    const user = { id: 1, name: 'John Doe' };
    const posts = [{ id: 1, title: 'Post 1' }];
    
    axios.get.mockResolvedValueOnce({ data: user }).mockResolvedValueOnce({ data: posts });

    const result = await fetchUserData(1);

    expect(result).toEqual({ user, posts });
  });
});

Этот тест проверяет работу с несколькими параллельными запросами. Метод mockResolvedValueOnce() используется для создания разных ответов для каждого запроса.

Заключение

Jest предоставляет гибкие возможности для тестирования API-запросов. С помощью мокирования, асинхронных функций и библиотек для создания фейковых серверов можно легко тестировать как отдельные запросы, так и сложные сценарии с множеством взаимозависимых запросов.