Назад в блог

~ 8-9 минут

Mock API во frontend-разработке: как тестировать интерфейс без готового backend

111

01.05.2026

Разбираемся, когда frontend-команде нужен mock API, чем отличаются моки в коде, json-server, MSW и свой тестовый сервер, и как проверять loading, error и empty states до готового backend.

Вадим Пашаев

Вадим Пашаев

Инженер, веб-разработчик, путешественник

Mock API во frontend-разработке: как не ждать backend

Наверное, почти у каждого frontend-разработчика была такая ситуация: макет уже есть, интерфейс нужно собирать, сроки идут, а backend еще не готов.

И тут начинается классика.

Сначала данные просто кладутся в компонент. Потом появляется отдельный mockData.js. Потом нужно проверить загрузку, ошибку, пустой список, форму, удаление, фильтры, пагинацию. И в какой-то момент становится понятно, что обычный массив объектов уже не очень помогает.

Вот здесь и появляется mock API.

Не как "игрушечный backend", а как рабочий инструмент, который позволяет фронтенду двигаться дальше, пока настоящая серверная часть еще в процессе.

Но важный момент: mock API - это не один конкретный инструмент. Это скорее подход. Иногда достаточно массива в коде. Иногда лучше поднять json-server. Иногда удобнее использовать MSW. А иногда проще написать маленький Express-сервер, как мы разбирали в статье про тестовое API на Express.

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

Что такое mock API

Mock API - это имитация настоящего API, с которой frontend может работать почти так же, как с реальным backend.

То есть интерфейс отправляет запрос:

GET /api/users

И получает ответ:

[
  {
    "id": 1,
    "name": "Алиса",
    "email": "alice@mail.ru",
    "status": "active"
  }
]

Для frontend-компонента не так важно, откуда пришел этот ответ: из настоящей базы данных, из db.json, из Service Worker или из локального Express-сервера.

Ему важно другое:

  • есть понятная структура данных;
  • есть успешные и ошибочные ответы;
  • можно проверить загрузку;
  • можно показать empty state;
  • можно протестировать форму;
  • можно не ждать backend, чтобы двигаться дальше.

По сути, mock API помогает отделить разработку интерфейса от готовности серверной части.

Когда моки действительно нужны

Я бы не использовал mock API просто ради того, чтобы "так правильно".

Он полезен, когда есть конкретная задача:

  • backend еще не готов, а frontend уже нужно собирать;
  • нужно показать клиенту или команде живой прототип;
  • нужно проверить разные состояния интерфейса;
  • нужно написать тесты без зависимости от реального сервера;
  • нужно договориться о будущей структуре ответа;
  • нужно быстро собрать MVP или pet-проект;
  • нужно сделать Storybook-сценарии с разными состояниями компонента.

Например, вы делаете страницу списка заказов. В красивом happy path все просто: пришел список, отрисовали карточки.

Но реальная работа начинается дальше:

  • заказов нет;
  • запрос идет 2 секунды;
  • сервер вернул 500;
  • один заказ в статусе paid, другой cancelled;
  • у заказа нет части необязательных полей;
  • пользователь нажал "удалить", а сервер ответил ошибкой.

Если эти сценарии не проверить на этапе разработки, они все равно всплывут. Просто позже, дороже и обычно в самый неудобный момент.

Иллюстрация про состояния интерфейса

Вариант 1. Моки прямо в коде

Самый простой способ - положить данные в отдельный файл.

export const users = [
  {
    id: 1,
    name: 'Алиса',
    email: 'alice@mail.ru',
    status: 'active'
  },
  {
    id: 2,
    name: 'Максим',
    email: 'max@mail.ru',
    status: 'blocked'
  }
]

И использовать их в компоненте:

import { users } from './mockData'

function UsersList() {
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  )
}

Для старта это нормально. Особенно если нужно быстро сверстать карточки, таблицу или список.

Но у такого подхода быстро появляются ограничения:

  • нет настоящего fetch;
  • сложно проверить loading;
  • сложно проверить HTTP-ошибки;
  • компонент может привыкнуть к данным не так, как они будут приходить с backend;
  • легко забыть, что в реальности ответ асинхронный.

Поэтому моки в коде хорошо подходят для самого первого слоя. Но если интерфейс уже работает с API, лучше имитировать именно API.

Вариант 2. json-server

json-server - это очень быстрый способ получить fake REST API из JSON-файла.

По текущему README проекта достаточно установить пакет, создать db.json и запустить сервер:

npm install json-server
npx json-server db.json

Создадим db.json:

{
  "users": [
    {
      "id": "1",
      "name": "Алиса",
      "email": "alice@mail.ru",
      "status": "active"
    },
    {
      "id": "2",
      "name": "Максим",
      "email": "max@mail.ru",
      "status": "blocked"
    }
  ]
}

После запуска можно обращаться к API:

GET http://localhost:3000/users
GET http://localhost:3000/users/1
POST http://localhost:3000/users
PATCH http://localhost:3000/users/1
DELETE http://localhost:3000/users/1

И вот это уже намного ближе к реальной разработке.

Frontend делает обычный запрос:

async function loadUsers() {
  const response = await fetch('http://localhost:3000/users')

  if (!response.ok) {
    throw new Error(`Ошибка запроса: ${response.status}`)
  }

  return response.json()
}

Здесь важно проверять response.ok. В документации MDN отдельно показано, что fetch не считает HTTP-статусы вроде 404 или 500 ошибкой Promise. Сервер ответил - значит Promise выполнился, а успешный это ответ или нет, нужно проверить самому.

json-server удобен, когда нужно:

  • быстро получить REST API;
  • хранить данные в понятном JSON;
  • проверять CRUD;
  • показать демо;
  • сделать прототип без написания backend-кода.

Но у него тоже есть границы.

Если нужно сложное поведение, кастомная бизнес-логика, авторизация, нестандартные ошибки или точная имитация production API, одного db.json может стать мало.

Вариант 3. Faker для реалистичных данных

Иногда проблема не в API, а в самих данных.

Два пользователя в массиве - это одно. А таблица на 100 строк, разные имена, email, роли, даты, города и статусы - уже совсем другое.

Для таких задач удобно использовать Faker. В документации Faker прямо указано, что библиотека подходит для unit tests, performance tests, demos и работы без готового backend.

Пример:

npm install @faker-js/faker --save-dev
import { faker } from '@faker-js/faker'

export function createUsers(count = 20) {
  return Array.from({ length: count }, () => ({
    id: faker.string.uuid(),
    name: faker.person.fullName(),
    email: faker.internet.email(),
    city: faker.location.city(),
    company: faker.company.name(),
    createdAt: faker.date.recent().toISOString()
  }))
}

Это полезно, когда нужно проверить:

  • длинные имена;
  • разные email;
  • большие списки;
  • таблицы и пагинацию;
  • карточки с разным количеством текста;
  • состояния, которые сложно придумать руками.

Единственное, что важно помнить: случайные данные не должны ломать договоренность о структуре API. Если backend будет возвращать firstName и lastName, а в моках у вас только name, потом придется переделывать frontend.

Вариант 4. MSW

MSW, или Mock Service Worker, работает немного иначе.

Он перехватывает сетевые запросы и возвращает мок-ответы на уровне сети. На сайте MSW это формулируется как подход, где вы описываете поведение сети, а не подменяете конкретный HTTP-клиент.

Это важная разница.

Ваш код может использовать fetch, Axios, React Query, SWR или что-то еще. А моки все равно работают вокруг сетевого слоя.

Пример handler:

import { http, HttpResponse } from 'msw'

export const handlers = [
  http.get('/api/users', () => {
    return HttpResponse.json([
      {
        id: 1,
        name: 'Алиса',
        status: 'active'
      }
    ])
  })
]

Для браузера обычно создается worker:

import { setupWorker } from 'msw/browser'
import { handlers } from './handlers'

export const worker = setupWorker(...handlers)

И запускается в development:

if (import.meta.env.DEV) {
  const { worker } = await import('./mocks/browser')
  await worker.start()
}

MSW особенно удобен, если вам нужно:

  • использовать одни и те же моки в разработке и тестах;
  • проверять разные network states;
  • мокать REST и GraphQL;
  • не менять код приложения ради моков;
  • показывать состояния компонентов в Storybook;
  • имитировать ошибки и edge cases.

Например, можно описать ошибку:

http.get('/api/users', () => {
  return HttpResponse.json(
    { message: 'Сервер временно недоступен' },
    { status: 500 }
  )
})

И проверить, как интерфейс показывает ошибку, не ломая настоящий backend и не дожидаясь, когда он реально упадет.

Что выбрать на практике

Я бы выбирал не по принципу "какой инструмент популярнее", а по задаче.

Если нужно просто сверстать карточки - хватит массива в коде.

Если нужен быстрый REST API для прототипа - хорошо подойдет json-server.

Если нужны реалистичные большие данные - добавьте Faker.

Если нужно проверять сетевые состояния, тесты и Storybook - смотрите в сторону MSW.

Если нужна кастомная логика, задержки, валидация, несколько связанных сущностей и поведение ближе к backend - можно написать маленький Express-сервер.

На практике эти подходы можно комбинировать.

Например:

  • Faker генерирует пользователей;
  • json-server быстро отдает их как REST API;
  • MSW перехватывает отдельные запросы в тестах;
  • Express используется там, где нужна логика сложнее обычного CRUD.

Главное - не забывать, зачем все это делается.

Mock API нужен не для того, чтобы заменить backend навсегда. Он нужен, чтобы быстрее проверить интерфейс и не остановить разработку.

Мини-карта перед созданием mock API

Перед тем как писать моки, я бы набросал простую карту.

Например, для страницы пользователей:

Экран: список пользователей

Данные:
- id
- name
- email
- status
- role

Endpoints:
- GET /users
- GET /users/:id
- POST /users
- DELETE /users/:id

Состояния:
- loading
- empty
- error 500
- not found 404
- validation error 400

После такой карты становится намного проще выбрать инструмент.

Если нужны только данные - массив или Faker.

Если нужны endpoints - json-server.

Если нужны network states в тестах - MSW.

Если нужна логика - Express.

И AI-инструменты здесь тоже могут помочь. Можно попросить ChatGPT или Codex с