Search code examples
node.jsrestsupertest

Node.js - Testing REST API routes with supertest


Req.body is not accessible in the routes while making a post request. It would be highly appreciative of someone if he/she help me getting through it. Here is screenshot of my microservice.test.js file. Am I missing something?

import request from "supertest";
import mongoose from "mongoose";

import config from "../config/env";
import routes from "../server/routes";

import { parseResponse, doRequest } from "../server/utils/helperFunctions";

const app = express();
app.use("/", routes);

jest.setTimeout(30000);

Solution

  • The code provided doesn't provide much insight, as I would expect all of the handling of the request to be in your route handler. Is the issue that you are unable to access the body when running tests with supertest? Or that it isn't working at all. More information would be very helpful.

    If it is a supertest issue, I would recommend checking out the docs for good examples. Here is one I pulled directly from the NPM site where they POST some data with a request body and then verify the response body:

    describe('POST /user', function() {
      it('user.name should be an case-insensitive match for "john"', function(done) {
        request(app)
          .post('/user')
          .send('name=john') // x-www-form-urlencoded upload
          .set('Accept', 'application/json')
          .expect(function(res) {
            res.body.id = 'some fixed id';
            res.body.name = res.body.name.toLowerCase();
          })
          .expect(200, {
            id: 'some fixed id',
            name: 'john'
          }, done);
      });
    });
    

    Also, if you are trying to test your server you should probably import your server code instead of creating a new express instance. For example, in your server code you'll have something like this:

    server.js

    const express = require('express');
    
    const app = express();
    app.use('/', ...) // middleware/route config
    ...
    
    module.exports = app;
    

    Your server would then use this server like this:

    index.js

    const app = require('./server')
    const port = 4000
    
    app.listen({ port }, () => {
      const location = `http://localhost:${port}`
      logger.info(`🚀 Server ready at ${location}`)
    })
    
    module.exports = app
    

    Now that you have structured your code this way, in your test you can import your server as well (so you are testing your actual server, not a new server that you made up):

    server.test.js

    const app = require('../../../server');
    const request = require('supertest')(app);
    
    describe('Server', () => {
      it('does a thing', async () => {
        const { body } = await request
          .post('http://path/to/test')
          .send({ data: 'some data' })
          .set('Content-Type', 'application/json')
          .set('Accept', 'application/json')
          .expect(200);
    
        expect(body.thing).toBeTrue();
      });
    });