Тело запроса супертеста не определено

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

Код из моего контроллера.ts

import { Router } from 'express';
import { z } from 'zod';
import { Kysely } from 'kysely';
import * as sprints from './services';
import * as schema from './schema';
import { DB } from '../../database';

export function createSprintsRouter(db: Kysely<DB>) {
  const router = Router();

  router.post('/', async (req, res) => {
    try {
      const parsedInput = schema.parseNewSprintInput.parse(req.body);
      const newSprint = await sprints.createSprint(db, parsedInput);
      res.status(201).json(newSprint);
    } catch (err) {
      if (err instanceof z.ZodError) {
        res.status(400).json({ err: err.errors });
      } else {
        res.status(500).json({ err: (err as Error).message });
      }
    }
  });

  return router;
}

Код из моего тестового файла Controller.spec.ts

import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import supertest from 'supertest';
import express from 'express';
import { Kysely } from 'kysely';
import { createSprintsRouter } from '../controller';
import { getTestDbInstance } from '../../../database/db-test';
import type { DB } from '@/database/types';

describe('Sprints Controller', () => {
  let testDb: Kysely<DB>;
  let app: express.Application;

  beforeAll(async () => {
    testDb = getTestDbInstance();
    const sprintsRouter = createSprintsRouter(testDb);
    app = express().use('/sprints', sprintsRouter);

    await testDb
      .insertInto('sprints')
      .values([
        { code: 'TST1', title: 'Test Sprint 1' },
        { code: 'TST2', title: 'Test Sprint 2' },
      ])
      .execute();
  });

  afterAll(async () => {
    await testDb.destroy();
  });

  describe("POST '/' endpoint", () => {
    it('should create a new sprint', async () => {
      const newSprint = { code: 'TST3', title: 'Test Sprint 3' };

      const res = await supertest(app)
        .post('/sprints')
        .set('Content-Type', 'application/json')
        .send(newSprint);

      expect(res.status).toBe(201);
      expect(res.body).toEqual(
        expect.objectContaining({
          code: 'TST3',
          title: 'Test Sprint 3',
        })
      );
      const allSprints = await supertest(app).get('/sprints');
      expect(allSprints.body).toHaveLength(3);
    });
  });
});

Я искал решения этой проблемы, и в большинстве случаев вам приходилось использовать app.use(bodyParser.json()); перед маршрутами (которые я использую). Но проблема все еще сохраняется.

Мое основное приложение.ts

import express from 'express';
import './bot/discordBot';
import messages from './modules/messages/controller';
import messageTemplates from './modules/message-templates/controller';
import db from './database/index';
import { createSprintsRouter } from './modules/sprints/controller';

const app = express();
app.use(express.json());
const sprintsRouter = createSprintsRouter(db);

app.use('/messages', messages);
app.use('/templates', messageTemplates);
app.use('/sprints', sprintsRouter);

export default app;
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Полезная нагрузка должна быть в форме Content-Type, установленной кодом.

Он состоит из двух частей, о которых нужно заботиться.

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

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

const payload = JSON.stringify(data);

Цитата:

Supertest+Jest не отправляет полезную нагрузку JSON

Привет. Удалось ли вам попробовать этот пост?

WeDoTheBest4You 24.06.2024 04:46
Ответ принят как подходящий

Проблема заключалась в том, что я не использовал экспресс express.json() в своем ТЕСТОВОМ файле Controller.spec.ts. Я все еще учусь программировать, поэтому, возможно, я ошибаюсь с технической точки зрения, но, насколько я понимаю, промежуточное программное обеспечение express.json() помогает анализировать тело json, которое мы отправляем через запрос к конечной точке. Поскольку я не реализовал его в своем TEST-файле, мой req.body всегда был неопределенным (поскольку он не анализировался должным образом). Я реализовал это промежуточное ПО в своем основном файле app.ts, поэтому думал, что использую его везде, но, насколько я понимаю, мой тестовый файл использует отдельный экземпляр экспресса, поэтому его настройки отличаются от моего основного файла. Подводя итог, убедитесь, что вы используете промежуточное программное обеспечение express.json() в своей настройке :).

Ваше чтение должно быть правильным: когда express.json загружается в тест, он отправляет полезную нагрузку в виде строки. В противном случае он этого не делает. Кстати, удалось ли вам попробовать следующее решение, просто хотелось бы знать, работает оно или нет?

WeDoTheBest4You 24.06.2024 04:56

Привет, ни одно предложенное решение мне не помогло. Хотя express.json() все решил

KarolisG 25.06.2024 10:41

Благодарим Вас за подтверждение. Также принял к сведению, что json() работает.

WeDoTheBest4You 25.06.2024 10:43

Другие вопросы по теме