Search code examples
node.jsexpresssinonsupertest

fake response(500) with sinon in post request NodeJs


can anyone help me out creating a fake response (500) for testing my API using "sinon" , am new to nodeJs , i have tried to test where the return status is 201 and it worked however am still not able to make the fake 500 response here is my code , thank you in advance

//knex 

app.post("/api/categories", function (req, rep) {
    knex('categories').insert(req.body)
        .then(() => rep.sendStatus(201).json({ message: "Category inserted" }))
        .catch((err) => {
            console.log(err)
            rep.status(500);
        })
});

// in my test js

var request=require('supertest');
var KnexApp=require('../KnexFolder/app');
var sinon = require("sinon");

describe("POST/users", ()=>{

  describe('when everything is fine and no errors', () => {
    it('should respond with status 201',async () => {
        const res = await request(KnexApp)
        .post('/api/categories')
        .send({
          name:"from test",
          img_id: 5
        })
      expect(res.statusCode).toEqual(201)
     
    })
  })

  describe('when There is internal server error', () => {


    it('should respond with status 500',async () => {
        sinon.stub('/api/categories', "post").throws(
            new Error({
              response: { status: 500},
            })
          );

          expect(res.statusCode).toEqual(500)
     
    })
  })
})

Solution

  • There are two testing strategies:

    1. Stub knex, query interface, and the resolved/rejected value. This way is easier than the second way, you don't need to set up a real testing database and populate testing data.

    2. As mentioned above, you need to set up a real testing database(run your migration script to create database and tables, create the seed testing data, etc...)

    I will use the first way to test your code. Since sinon doesn't support stub a function export defaults by a module. We need to use proxyquire package.

    app.js:

    const express = require('express');
    
    const knex = require('knex')({
      client: 'mysql',
      connection: {
        host: '127.0.0.1',
        port: 3306,
        user: 'your_database_user',
        password: 'your_database_password',
        database: 'myapp_test',
      },
    });
    const app = express();
    
    app.use(express.json());
    app.post('/api/categories', function (req, rep) {
      console.log(req.body);
      knex('categories')
        .insert(req.body)
        .then(() => rep.sendStatus(201).json({ message: 'Category inserted' }))
        .catch((err) => {
          console.log(err);
          rep.sendStatus(500);
        });
    });
    
    module.exports = app;
    

    app.test.js:

    const request = require('supertest');
    const sinon = require('sinon');
    const proxyquire = require('proxyquire');
    
    describe('POST/users', () => {
      describe('when everything is fine and no errors', () => {
        it('should respond with status 201', async () => {
          const queryInterfaceStub = {
            insert: sinon.stub().resolves(),
          };
          const knexStub = sinon.stub().returns(queryInterfaceStub);
          const KnexStub = sinon.stub().returns(knexStub);
          const KnexApp = proxyquire('./app', {
            knex: KnexStub,
          });
          const res = await request(KnexApp).post('/api/categories').send({
            name: 'from test',
            img_id: 5,
          });
          sinon.assert.match(res.statusCode, 201);
        });
      });
    
      describe('when There is internal server error', () => {
        it('should respond with status 500', async () => {
          const queryInterfaceStub = {
            insert: sinon.stub().rejects(new Error('fake error')),
          };
          const knexStub = sinon.stub().returns(queryInterfaceStub);
          const KnexStub = sinon.stub().returns(knexStub);
          const KnexApp = proxyquire('./app', {
            knex: KnexStub,
          });
          const res = await request(KnexApp).post('/api/categories').send({});
    
          sinon.assert.match(res.statusCode, 500);
        });
      });
    });
    

    Test result:

      POST/users
        when everything is fine and no errors
    { name: 'from test', img_id: 5 }
    Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
        at ServerResponse.setHeader (_http_outgoing.js:558:11)
        at ServerResponse.header (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/response.js:771:10)
        at ServerResponse.send (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/response.js:170:12)
        at ServerResponse.json (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/express/lib/response.js:267:15)
        at /Users/dulin/workspace/github.com/mrdulin/expressjs-research/src/stackoverflow/71565119/app.js:20:37
        at processTicksAndRejections (internal/process/task_queues.js:93:5) {
      code: 'ERR_HTTP_HEADERS_SENT'
    }
          ✓ should respond with status 201 (436ms)
        when There is internal server error
    {}
    Error: fake error
        at Context.<anonymous> (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/src/stackoverflow/71565119/app.test.js:27:38)
        at callFn (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runnable.js:364:21)
        at Test.Runnable.run (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runnable.js:352:5)
        at Runner.runTest (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:677:10)
        at /Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:801:12
        at next (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:594:14)
        at /Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:604:7
        at next (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:486:14)
        at Immediate.<anonymous> (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:572:5)
        at processImmediate (internal/timers.js:461:21)
          ✓ should respond with status 500
    
    
      2 passing (448ms)