Express POST API Route not receiving a Supertest request

Tags: , , , ,



I am trying to test an Express API POST Route that uses Express Validator for check:

usersRouter.post(
  '/',
  [
    check('name', 'Please enter a name.').not().isEmpty(),
    check('email', 'Please enter a valid email.').isEmail(),
    check(
      'password',
      'Please enter a password of 6 characters or more.'
    ).isLength({ min: 6 }),
  ],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      console.log('errors: ', errors);
      return res.status(400).json({ errors: errors.array() });
    }

    const { name, email, password } = req.body;
    
    try {
        //...
    }
    catch {
        //...
    }
  }
);

This API route expects to receive a request consisting of a body that contains the fields, name, email, and password:

const { name, email, password } = req.body

In order to test this route, I have a test file using supertest and jest:

const mongoose = require('mongoose');
const supertest = require('supertest');
const app = require('../app');
const testApi = supertest(app);
const User = require('../models/User');

test('a token is returned', async () => {
  // Create a new test user for the HTTP request.
  const newTestUser = {
    name: 'bob',
    email: 'test@test.com',
    password: 'newtestpw',
  };
  const { name, email, password } = newTestUser;
  const body = await JSON.stringify({ name, email, password });

  // Execute the test.
  const config = {
    headers: {
      'Content-Type': 'application/json',
    },
  };
  let result = await testApi.post('/api/users', body, config);

  expect(result.status).toBe(200);
  expect(result.headers).toHaveProperty('token');
});

afterAll(async () => {
  await mongoose.connection.close();
});

When I execute this test, each check in the POST API route fails. The following errors is returned:

    errors:  Result {
      formatter: [Function: formatter],
      errors:
       [ { value: undefined,
           msg: 'Please enter a name.',
           param: 'name',
           location: 'body' },
         { value: undefined,
           msg: 'Please enter a valid email.',
           param: 'email',
           location: 'body' },
         { value: undefined,
           msg: 'Please enter a password of 6 characters or more.',
           param: 'password',
           location: 'body' } ] }

Why is the API route not receiving the request I’m sending using Supertest?

Answer

Well, it seems that you’re not sending your values right. Look closely at where you send your name, email and password, and how you send them. You can try going to your route and console.log the values it’s getting. And look in how the api.post function actually works. I suggest looking on the Supertest github page and Superagent docs

Just in case you want to try to solve the problem on your own, I hid the solution in the spoiler. But in short, first:

You don’t need to stringify your body. You should send it as a usual JavaScript object. Also, you don’t need to await the JSON.stringify, as it doesn’t return a promise, it’s synchronous

Second:

The api.post function only takes the URL as its argument. To send any data you want along with the request you need to chain .send(data) after the .post

Third:

The headers are also set by chaining the .set('Header', 'value') method before or after the .send

So in the end, your request should look something like this.

testApi
  .post(url)
  .set('Content-Type', 'application/json')
  .send(newTestUser)


Source: stackoverflow