Search code examples
node.jsexpressmocha.jschaisupertest

Supertest fails to test repeated post request


I'm testing an api that creates users. The api does not allow the creation of users with the same login value. So I wrote the tests below:

const app = require('../config/express'); //exports a configured express app
const request = require('supertest');
const {populateUsers} = require('../seeders/users.seed');

beforeEach(populateUsers);//drop and populate database with some seeders

describe('POST /v1/users', () => {
  it('#Post a new user - 201 status code', (done) => {
    request(app)
        .post('/v1/users')
        .send({
                login:'user-teste-01',
                password: 'pass01'
        }).expect(201, done);           
  });
  it('#Post repeated login - 400 status code', (done) => {
    request(app)
        .post('/v1/users')
        .send({
                login:'user-teste-01',
                password: 'pass01'
        }).expect(400, done);
  });
});

The firts test works, but the second test returns the following error:

Error: expected 400 "Bad Request", got 201 "Created"

I did the tests manually and the api works correctly (returning 400 status code).

Where did I make the mistake in this test?


Solution

  • it is because you have beforeEach that reset your database. This hook will be executed in every test so in your 400 status code, you no longer have user user-teste-01 because it has been reset by beforeEach.

    There are some solutions for this:

    #1 Use login and password that exist in your seed

    it('#Post repeated login - 400 status code', (done) => {
      request(app)
        .post('/v1/users')
        .send({
          login: 'user-exist-in-seed',
          password: 'pass01'
        }).expect(400, done);
    });
    

    #2 Create a user again before running the scenario

    context('when user is already exist', function() {
      beforeEach(function() {
        // create a user `user-teste-01`
        // use beforeEach so it will be executed after seeding
      })
    
      it('#Post repeated login - 400 status code', (done) => {
        request(app)
          .post('/v1/users')
          .send({
            login: 'user-teste-01',
            password: 'pass01'
          }).expect(400, done);
      });
    });
    

    3 Use before instead of beforeEach for seeding

    It will run once before all tests

    before(populateUsers);//drop and populate database with some seeders