Как тестировать побочные эффекты в Node.js

Написание тестов для приложения — самый сложный, но необходимый элемент процесса разработки. Тесты обеспечивают правильное сопровождение кода и улучшают его качество.

В этом руководстве мы покажем лучший способ обработки побочных эффектов в ваших приложениях Node.js.

Но сначала давайте дадим определение побочных эффектов.

Что такое побочные эффекты?

Хотя часто хорошей идеей является сделать ваш код как можно более свободным от побочных эффектов, написание кода с побочными эффектами неизбежно в большинстве проектов.

В программировании считается, что функция или выражение имеет побочный эффект, если она использует или изменяет состояние за пределами своей области применения, например:

  • чтение/запись данных в файл
  • выполнение сетевого запроса к API
  • вызов другой функции с побочным эффектом

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

Тесты API и инициирование побочных эффектов

Тесты API оценивают надежность, функциональность, производительность и безопасность приложения. Для выполнения этих тестов требуется три шага:

  1. Отправить запрос с необходимыми входными данными.
  2. Получить ответ.
  3. Проверить, что ответ вернул ожидаемый результат.

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

Традиционно, чтобы справиться с этими побочными эффектами, вам приходилось имитировать действия ввода-вывода (Input/Output), регулярно изменяя свой код, чтобы заменить ввод-вывод кодом-заглушкой.

Но есть лучший способ: использовать библиотеку побочных эффектов!

Что такое библиотека побочных эффектов?

Библиотека побочных эффектов — это библиотека Javascript, которая позволяет записывать все побочные эффекты в одно место и загружать реальное/заглушечное поведение во время выполнения.

Зачем использовать побочные эффекты для вашего приложения Node.js?

Есть несколько преимуществ использования библиотеки побочных эффектов для тестирования вашего приложения Node.js:

  • Она позволяет вам определить побочные эффекты каждой операции в вашем приложении.
  • Вам не нужно иметь дело с имитатором API или регулярно настраивать его.
  • У вас есть единое место, где хранятся все побочные эффекты вашего приложения (в терминологии DDD это слой инфраструктуры).
  • Вашу программу будет легко тестировать.
  • Вы создаете документацию для побочных эффектов вашего приложения, создавая файл побочных эффектов.

Предварительные условия

Прежде чем начать работу с этим учебником, убедитесь, что вы выполнили следующие требования:

  • У вас установлен Node.js
  • У вас установлен Postman
  • У вас есть предварительные знания о Typescript

Настройка Typescript

Чтобы продемонстрировать, как можно использовать побочные эффекты в приложении, мы создадим сервер Node.js, который будет работать с приложением todo и создавать побочные эффекты для приложения.

Мы начнем с настройки Typescript для проекта. Установите Typescript глобально с помощью команды ниже:

npm install -g typescript
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем создайте папку проекта и файл tsconfig.json для конфигурации Typescript с помощью команд ниже:

mkdir side-effect-demo && cd side-effect-demo
tsc --init
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь замените содержимое файла tsconfig.json следующими конфигурациями.

{
    "compilerOptions": {
      "target": "es2015",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
      "module": "commonjs",                                /* Specify what module code is generated. */
      "rootDir": "./",                                     /* Specify the root folder within your source files. */
      "outDir": "./dist",                                  /* Specify an output folder for all emitted files. */
      "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
      "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
      "strict": true,                                      /* Enable all strict type-checking options. */
      "skipLibCheck": true,

    },
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Настройка сервера Node.js

Когда Typescript настроен для проекта, мы инициализируем проект Node.js с помощью команды ниже.

npm init -y
Войти в полноэкранный режим Выйти из полноэкранного режима

Приведенная выше команда создаст файл package.json для хранения зависимостей вашего проекта. Теперь установите необходимые зависимости и devDependencies командой ниже:

npm i express side-effect-js && npm i -D typescript tsc ts-node-dev @types/express @types/node
Войти в полноэкранный режим Выйти из полноэкранного режима

После завершения установки создайте файл index.ts. Обновите script в файле package.json со следующими конфигурациями.

"scripts": {
  "dev": "ts-node-dev --clear index.ts",
  "build": "tsc",
  "start": "node dist/index.js"
},
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь создайте Express-сервер в файле index.ts с помощью приведенного ниже фрагмента кода:

import express, { Express } from "express";
const app: Express = express();

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем выполните эту команду в терминале, чтобы запустить сервер.

npm run dev
Войти в полноэкранный режим Выйти из полноэкранного режима

Это позволит запустить сервер в режиме разработки и включить горячую перезагрузку для отражения последних изменений в приложении.

Создание побочных эффектов

Сейчас мы должны создать бизнес-логику для приложения. Но вместо метода MVC мы воспользуемся методом побочных эффектов. Для этого создайте новый файл side-effect.ts в корневом каталоге вашего проекта. Добавьте этот фрагмент кода в файл side-effect.ts.

import SideEffectJS from "side-effect-js";

const todos = [
  {
    id: 1,
    text: "Learn JavaScript",
    completed: true,
  },
  {
    id: 2,
    text: "Learn React",
    completed: false,
  },
  {
    id: 3,
    text: "Learn Redux",
    completed: false,
  },
];

type Todos = {
  id: number,
  text: string,
  completed: boolean,
};
Вход в полноэкранный режим Выход из полноэкранного режима

В приведенном выше фрагменте кода мы импортируем SideEffectJS, создаем фиктивные данные todos и тип Todos, который будет служить моделью для todos.

Теперь давайте создадим побочный эффект, получим и создадим todo. Каждый побочный эффект имеет реальную функцию, имитационную функцию и идентификатор. id должен быть уникальным для каждого побочного эффекта.

//all todos
const getTodosReal = (): Todos[] => {
  return todos;
}
const getTodoMock = (): Todos[] => {
  return todos
}

//create Todo
const addTodoReal = (todo: Todos): Todos[] => {
  todos.push(todo);
  return todos;
}
const addTodoMock = (todo: Todos): Todos[] => {
  todos.push(todo);
  return todos;
}
const AllTodos = SideEffectJS.CreateEffectTyped<Todos, Todos[]>('all-todos', getTodosReal, getTodoMock);
const AddTodo = SideEffectJS.CreateEffectTyped<Todos, Todos[]>('add-todo', addTodoReal, addTodoMock);

export default [AllTodos, AddTodo];
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы создаем реальную и макетную функции для получения и создания todo. Затем мы используем CreateEffectTyped для создания побочных эффектов для функций. Мы также указываем типы T и R в методе CreateEffectTyped — макетная и реальная функции получают (T), а ожидаемые результаты для макетной и реальной функции (R). Наконец, мы экспортируем побочные эффекты.

Создание маршрутов API

Теперь, когда мы создали побочные эффекты для приложения, давайте определим маршруты API для их использования. Сначала нам нужно импортировать модуль побочных эффектов и только что созданные побочные эффекты в наш корневой файл index.ts.

...
import SideEffectJS from "side-effect-js";
import sideEffect from "./side-effect";
Вход в полноэкранный режим Выход из полноэкранного режима

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

...
SideEffectJS.Load(sideEffect);

const getTodos = SideEffectJS.Get('all-todos');
const createTodo = SideEffectJS.Get('add-todo');
Войти в полноэкранный режим Выход из полноэкранного режима

Далее нам нужно определить два маршрута API и вызвать их с помощью приведенного ниже фрагмента кода.

app.use(express.json());
app.get("/api/todo", async (req, res) => {
  res.json({ data: await getTodos() });
});

app.post("/api/todo", async (req, res) => {
  res.json({ data: await createTodo(req.body) });
});
Вход в полноэкранный режим Выйти из полноэкранного режима

Мы разбираем входящие JSON-запросы, помещаем разобранные данные в req и определяем маршруты API.

Тестирование API для вашего приложения Node.js

Теперь, когда мы создали API для приложения, давайте протестируем его. Запустите Postman и отправьте GET-запрос на URL localhost:3000/api/todo, чтобы получить тодосы.

Затем отправьте POST-запрос и добавьте в тело запроса следующие данные JSON.

{
    "id":4,
    "text":"Learn Python",
    "completed":false
}
Войти в полноэкранный режим Выход из полноэкранного режима

Подведение итогов: Тестирование вашего приложения Node.js с помощью побочных эффектов

В этом руководстве мы узнали, как протестировать приложение Node.js с помощью побочных эффектов. Мы начали с определения библиотеки побочных эффектов и рассказали о том, зачем ее использовать. Затем мы создали приложение todo.

Надеюсь, эта статья помогла вам понять, как лучше тестировать ваше приложение Node.js. Узнайте больше о побочных эффектах из документации.

До следующего раза, счастливого кодинга!

P.S. Если вам понравилась эта статья, подпишитесь на наш список JavaScript Sorcery для ежемесячного глубокого погружения в более волшебные советы и трюки JavaScript.

P.P.S. Если вам нужен APM для вашего Node.js приложения, обратите внимание на AppSignal APM для Node.js.

Оцените статью
devanswers.ru
Добавить комментарий