nodejs - 存储module.exports函数与sinon

时间:2017-02-23 14:03:55

标签: mysql node.js sinon chai

我有expressjs个应用,其中包含以下routesmiddleware个模块。我正在尝试使用mochachaihttp-chaisinonjs来测试路线模块。 API使用mysql并且为了测试路由模块,我将它全部模块化,以便我可以存根mysql模块。 但是,当我尝试存根middleware/index时,我遇到了麻烦。如果我试图正常地要求index,那么该模块实际上并没有被删除。如果我尝试使用require.cache[require.resolve('./../../lib/routes/middleware/index')];要求它,它似乎存根,但indexStub.returns(indexObj)会返回错误TypeError: indexStub.returns is not a functionTypeError: indexStub.restore is not a function

如何正确存根index.js以控制代码流并防止它尝试连接到mysql?

routes.js

'use strict';

const express =      require('express');
const router =       express.Router();
const configs =      require('./../config/configs');
const middleware =   require('./middleware/index');
const bodyParser =   require('body-parser');

const useBodyParserJson = bodyParser.json({
  verify: function (req, res, buf, encoding) {
    req.rawBody = buf;
  }
});

const useBodyParserUrlEncoded = bodyParser.urlencoded({extended: true});

// creates a new post item and return that post in the response
router.post('/posts', useBodyParserUrlEncoded, useBodyParserJson, middleware.validatePostData, middleware.initializeConnection, middleware.saveNewPost, middleware.closeConnection, function(req, res) {
  if (res.statusCode === 500) {
    return res.send();
  }
  if (res.statusCode === 405) {
    return res.send('Item already exists with slug ' + req.body.slug + '. Invalid method POST');
  }
  res.json(res.body).end();
});

module.exports = router;

中间件/ index.js

'use strict';

const configs =  require('./../../config/configs');
const database = require('./../../factories/databases').select(configs.get('STORAGE'));
const dataV = require('./../../modules/utils/data-validator');


module.exports = {
  initializeConnection: database.initializeConnection, // start connection with database
  closeConnection:      database.closeConnection,      // close connection with database
  saveNewPost:          database.saveNewPost,          // creates and saves a new post
  validatePostData:     dataV.validatePostData,        // validates user data
};

SPEC-routes.js

'use strict';

var chai = require('chai');
var chaiHttp = require('chai-http');
var sinonChai = require("sinon-chai");
var expect = chai.expect;
var sinon = require('sinon');
chai.use(sinonChai);
chai.use(chaiHttp);
var app = require('./../../app');

  describe('COMPLEX ROUTES WITH MIDDLEWARE', function() {
    var indexM = require.cache[require.resolve('./../../lib/routes/middleware/index')];

    describe('POST - /posts', function() {
      var indexStub,
        indexObj;

      beforeEach(function() {
        indexStub = sinon.stub(indexM);
        indexObj = {
          'initializeConnection': function(req, res, next) {
            return next();
          },
          'closeConnection': function(req, res, next) {
            return next();
          },
          'validatePostData': function(req, res, next) {
            return next();
          }
        };
      });

      afterEach(function() {
        indexStub.restore();
      });

      it('should return a 500 response', function(done) {
        indexObj.saveNewPost = function(req, res, next) {
          res.statusCode = 500;
          return next();
        };
        indexStub.returns(indexObj);
        chai.request(app)
          .post('/posts')
          .send({'title': 'Hello', 'subTitle': 'World', 'slug': 'Example', 'readingTime': '2', 'published': false})
          .end(function(err, res) {
            expect(res).to.have.status(500);
            done();
          });
      });
    });
  });

1 个答案:

答案 0 :(得分:0)

您根本不使用Sinon,因为它根本不处理模块加载。我看到您已经开始使用内部Node API手动执行此操作,但是我建议您以we advise in the Sinon docs regarding this usecase:使用proxyquire的方式进行操作。

它使您可以将require的{​​{1}}调用替换为您自己喜欢的模拟对象(可能使用sinon制作)。

您将使用类似以下的方式:

./middleware/index.js