Question

How can I test rest api using express and only JEST?

*
470 visibility 0 arrow_circle_up 0 arrow_circle_down

Can I use only JEST to test my rest API endpoints in express? I've searched several articles and also saw some of the questions of stackoverflow to see how can I do this. But the problem is for testing in express most of the people are using mocha/chai or supertest. But I want to use only JEST in my test. Is this possible?

this is my code so far where I want to implement this test:

index.js

const express = require('express');
const app = express();

app.post('/insert', function (req, res, next) {

    const values = req.body; //name, roll

      pool.query(`INSERT INTO student SET ?`, [values], (err, result) => {

        if (err){
          let err = new Error('Not Connected');
          next(err);
      } else {
          res.status(201).json({ msg: `added ${result.insertId}`});
          console.log(result);
        }

      });

});

what i've tried so far is : index.test.js:

const express = require('express');
const app = express();

app.use('../routes');

test('Test POST, Success Scenario', async () => {
    const response = await app.post('/insert')({
        const values //dummy values will be insert here
    });

    expect(response.statusCode).toBe(200);

});

I know my test code is not correct, it's just a pseudocode I'm actually confused how I will hit the end point here


    Answer - 1
    0 arrow_circle_up 0 arrow_circle_down

    Here is the unit test solution for testing Nodejs web framework express REST API ONLY USING JEST:

    index.js:

    const express = require('express');
    const { Pool } = require('pg');
    
    const app = express();
    const pool = new Pool();
    
    app.post('/insert', (req, res, next) => {
      const values = req.body;
    
      pool.query(`INSERT INTO student SET ?`, [values], (err, result) => {
        if (err) {
          err = new Error('Not Connected');
          next(err);
        } else {
          res.status(201).json({ msg: `added ${result.insertId}` });
          console.log(result);
        }
      });
    });
    

    index.spec.js:

    const routes = {};
    jest.mock('express', () => {
      const mExpress = {
        post: jest.fn((path, controller) => {
          routes[path] = controller;
        })
      };
      return jest.fn(() => mExpress);
    });
    
    let queryCallback;
    jest.mock('pg', () => {
      const mpool = {
        query: jest.fn((query, values, callback) => {
          queryCallback = callback;
        })
      };
      const mPool = jest.fn(() => mpool);
      return { Pool: mPool };
    });
    
    require('./index');
    const express = require('express');
    const { Pool } = require('pg');
    const app = express();
    const pool = new Pool();
    
    describe('insert', () => {
      afterEach(() => {
        jest.restoreAllMocks();
      });
      test('should insert data correctly', done => {
        const logSpy = jest.spyOn(console, 'log');
        expect(app.post).toBeCalledWith('/insert', expect.any(Function));
        const mReq = { body: 1 };
        const mRes = { status: jest.fn().mockReturnThis(), json: jest.fn().mockReturnThis() };
        routes['/insert'](mReq, mRes);
        expect(pool.query).toBeCalledWith('INSERT INTO student SET ?', [1], expect.any(Function));
        const mResult = { insertId: 1 };
        queryCallback(null, mResult);
        expect(mRes.status).toBeCalledWith(201);
        expect(mRes.status().json).toBeCalledWith({ msg: 'added 1' });
        expect(logSpy).toBeCalledWith(mResult);
        done();
      });
    
      test('should call error handler middleware', () => {
        expect(app.post).toBeCalledWith('/insert', expect.any(Function));
        const mReq = { body: 1 };
        const mRes = { status: jest.fn().mockReturnThis(), json: jest.fn().mockReturnThis() };
        const mNext = jest.fn();
        routes['/insert'](mReq, mRes, mNext);
        expect(pool.query).toBeCalledWith('INSERT INTO student SET ?', [1], expect.any(Function));
        const mError = new Error('network error');
        queryCallback(mError, null);
        expect(mNext).toBeCalledWith(new Error('Not Connected'));
      });
    });
    

    Unit test result with 100% coverage:

     PASS  src/stackoverflow/56635460/index.spec.js (7.391s)
      insert
        ✓ should insert data correctly (15ms)
        ✓ should call error handler middleware (1ms)
    
      console.log node_modules/jest-mock/build/index.js:860
        { insertId: 1 }
    
    ----------|----------|----------|----------|----------|-------------------|
    File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    ----------|----------|----------|----------|----------|-------------------|
    All files |      100 |      100 |      100 |      100 |                   |
     index.js |      100 |      100 |      100 |      100 |                   |
    ----------|----------|----------|----------|----------|-------------------|
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        8.571s
    

    Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/56635460

    by   *