dimanche 4 juin 2017

How to stub a function in a module?

I build express app, there is a route A use many middlewares:

// fblogin.js
const saveUser = require('./middlewares').saveUser;
const issueJWT = require('./middlewares').issueJWT;

const exchangeLongTimeToken = (a) => { //return promise to call API };
const retrieveUserInfo = (b) => { //return promise to call API };

const service = {
    exchangeLongTimeToken,
    retrieveUserInfo,
};

const asyncAll = (req, res) => { //use Promise.all() to get service.exchangeLongTimeToken and service.retrieveUserInfo};

router.post('/', [asyncAll, saveUser, issueJWT], (req, res) => {
    res.json({
        url: '/authok.html',
        token: res.locals.token,
    });
});

module.exports = { router, service };

And this is my middlewares.js:

const saveUser = (req, res, next) => { //save user };
const issueJWT = (req, res, next) => { //issue jwt };

module.exports = { saveUser, issueJWT };

It works well. But got problem when I tried to write the test. This is my test, I use mocha, chai, supertest and sinon:

const sinon = require('sinon');
const middlewares = require('../../../../src/routes/api/auth/shared/middlewares');
const testData = require('../../testdata/data.json');
let app = require('../../../../src/config/expressapp').setupApp();
const request = require('supertest');
let service = require('../../../../src/routes/api/auth/facebook/fblogin').service;


describe('I want to test', () => {
    context('Let me test', function () {
        const testReq = {name: 'verySad'};

        beforeEach(() => {
            sinon.stub(middlewares, 'saveUser').callsFake((req, res, next)=>{
                console.log(req);
            });


            sinon.stub(service, 'exchangeLongTimeToken').callsFake((url) => {
                return Promise.resolve(testData.fbLongTimeToken);
            });

            sinon.stub(service, 'retrieveUserInfo').callsFake((url) => {
                return Promise.resolve(testData.fbUserInfo);
            });

        });


        it('Should return 400 when bad signedRequest', () => {

            return request(app).post(facebookAPI).send(testReq).then((response) => {
                console.log(1);
            });
        });
});

What is the problem
You could see that there are 3 stubs, 1 for middlewares.saveUser and 2 for services.XXXX which is in the same file of the route.

The problem is that, the 2 stubs works while the 1 for middlewares.saveUser not work, always trigger the original one.

How to get the stub work?
The only way to get it work, is to put the stub at the top of test file, just after that middleware require.

I tried:
1. Use 3rd party modules like proxyquire, rewire
2. Use node's own delete require.cache[middlewares] and 'app' and re-require them.
3. Many other tricks.
4. Use jest's mock, but still only works if I put it at the top of the file.

What is the way of solving this problem without putting the stub at the top of the test file? Thanks!

Aucun commentaire:

Enregistrer un commentaire