Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing ES6 function import in mocha using sinon stub

I'm trying to stub function called on one of my routes in express Router with request from supertest library. I see that function foo is called correctly, unfortunately it is not replaced by stub function I wrote in test. Code is written in ES6 and I'm using babel-register and babel-polyfill to make it work.

I run testing script using

./node_modules/mocha/bin/mocha server --timeout 10000 --compilers js:babel-register --require babel-polyfill --recursive

router.js

import {foo} from '../controller';
const router = new Router();
router.route(ROUTE).post(foo);

controller.js

export function foo(req, res) {
    res.status(200).send({
        ok: 'ok'
    });
}

test.js

import request from 'supertest';
import sinon from 'sinon';
import {app} from 'app';
import * as controller from 'controller';

const agent = request.agent(app);
describe('Admin routes tests', () => {
    it('Tests login admin route', async () => {
    const bar = () => {
        console.log('bar');
    };
    sinon.stub(controller, 'foo', bar);
    const req = await agent
        .post(ROUTE)
        .set('Accept', 'application/json');
    console.log(stub.calledOnce); // false
    });
});

Any help would be much appreciated.

like image 302
ruciu Avatar asked Nov 08 '22 03:11

ruciu


1 Answers

Here is the solution:

app.js:

import express from "express";
import * as controller from "./controller";

const app = express();

app.post("/foo", controller.foo);

export { app };

controller.js:

export function foo(req, res) {
  res.status(200).send({ ok: "ok" });
}

test.js:

import request from "supertest";
import sinon from "sinon";
import * as controller from "./controller";
import { expect } from "chai";

describe("Admin routes tests", () => {
  it("Tests login admin route", (done) => {
    const bar = () => {
      console.log("bar");
    };
    const fooStub = sinon.stub(controller, "foo").callsFake(bar);
    const { app } = require("./app");
    const agent = request.agent(app);
    agent
      .post("/foo")
      .set("Accept", "application/json")
      .timeout(1000)
      .end((err, res) => {
        sinon.assert.calledOnce(fooStub);
        expect(res).to.be.undefined;
        expect(err).to.be.an.instanceof(Error);
        done();
      });
  });
});

Since you stub foo controller and its return value is undefined. For supertest, there is no response, something like res.send(), the server will hang until the mocha test timeout and it will cause test failed.

.mocharc.yml:

recursive: true
require: ts-node/register
timeout: 2000
diff: true
inline-diffs: true

We add .timeout(1000) for supertest, because we know it will timeout(You stub the foo controller with bar). And, make an assertion for this timeout error.

Integration test result with coverage report:

  Admin routes tests
bar
    ✓ Tests login admin route (1341ms)


  1 passing (1s)

---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |    95.65 |      100 |       80 |    95.65 |                   |
 app.ts        |      100 |      100 |      100 |      100 |                   |
 controller.ts |       50 |      100 |        0 |       50 |                 2 |
 test.ts       |      100 |      100 |      100 |      100 |                   |
---------------|----------|----------|----------|----------|-------------------|

Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/41600031

like image 175
slideshowp2 Avatar answered Nov 14 '22 22:11

slideshowp2