Search code examples
javascriptnode.jsrequestnestjssupertest

(NestJS + Supertest) How do I test a bad request scenario?


I've struggling with this for a few hours. I'm coding a sample API with NestJS, and I'm adding some tests for an endpoint that receives latitude and longitude as query params and returns an array of restaurants located up to a certain distance. I added the necessary type validations for the query params, but I'm unable to trigger a bad request scenario in the tests. My test file looks something like this:

import { INestApplication } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import * as request from 'supertest';
import { RestaurantController } from './restaurant.controller';
import { RestaurantService } from './restaurant.service';
import { successResponse } from '../../test/mocks';

describe('RestaurantController', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const testApp: TestingModule = await Test.createTestingModule({
      controllers: [RestaurantController],
      providers: [RestaurantService],
    }).compile();

    app = testApp.createNestApplication();
    await app.init();
  });

  describe('GET /restaurant/location', () => {
    const url = '/restaurant/location';

    it('should return a list of near restaurants', () => {
      return request(app.getHttpServer())
        .get(url)
        .query({ latitude: -34.661369, longitude: -58.362257 })
        .expect(200)
        .expect(successResponse);
    });

    it('should throw an error because the latitude is invalid', () => {
      return request(app.getHttpServer())
        .get(url)
        .query({ latitude: 'I am not a valid latitude', longitude: -58.362257 })
        .expect(400);
    });
  });
});

The success scenario works as expected, but in the second case, when I'm expecting to receive a status 400, the request keeps resolving to 200. This is the error message I get on the terminal:

 FAIL  src/restaurant/restaurant.controller.spec.ts
  ● RestaurantController › GET /restaurant/location › should throw an error because the latitude is invalid

    expected 400 "Bad Request", got 200 "OK"

      44 |         .get(`${url}?latitude=invalid&longitude=-58.362257`)
      45 |         .query({ latitude: 'I am not a valid latitude', longitude: -58.362257 })
    > 46 |         .expect(400);
         |          ^
      47 |     });
      48 |   });
      49 | });

      at Object.<anonymous> (src/restaurant/restaurant.controller.spec.ts:46:10)
      ----
      at Test._assertStatus (node_modules/supertest/lib/test.js:252:14)
      at node_modules/supertest/lib/test.js:306:17
      at Test._assertFunction (node_modules/supertest/lib/test.js:285:13)
      at Test.assert (node_modules/supertest/lib/test.js:164:23)
      at Server.localAssert (node_modules/supertest/lib/test.js:120:14)

If I do the exact same request in the browser or postman, it fails as expected. What am I missing?

Thanks in advance.


Solution

  • So, the problem was pretty simple. I'm using ValidationPipe to validate the query params, and for some reason I assumed that it was being bound to the testApp out of the box. Thing is, it has to be done explicitly:

        const testApp: TestingModule = await Test.createTestingModule({
          controllers: [RestaurantController],
          providers: [RestaurantService],
        }).compile();
    
        app = testApp.createNestApplication();
        // This was the missing part
        app.useGlobalPipes(
          new ValidationPipe({ whitelist: true, transform: true }),
        );
        await app.init();