【问题标题】:How to mock middleware in Express to skip authentication for unit test?如何在 Express 中模拟中间件以跳过单元测试的身份验证?
【发布时间】:2017-06-19 03:01:14
【问题描述】:

我在 Express 中有以下内容

 //index.js

 var service = require('./subscription.service');
 var auth = require('../auth/auth.service');
 var router = express.Router();

 router.post('/sync', auth.isAuthenticated, service.synchronise);

 module.exports = router;

我想覆盖或模拟 isAuthenticated 以返回此

auth.isAuthenticated = function(req, res, next) { 
  return next(); 
}

这是我的单元测试:

it('it should return a 200 response', function(done) {

  //proxyquire here?

  request(app).post('/subscriptions/sync')
  .set('Authorization','Bearer '+ authToken)
  .send({receipt: newSubscriptionReceipt })
  .expect(200,done);
});

我尝试使用 proxyquire 模拟 index.js - 我想我需要存根路由器? 我也尝试在测试中覆盖

app.use('/subscriptions', require('./api/subscription'));

必须有一个简单的方法来模拟这个,所以我不需要对请求进行身份验证。有什么想法吗?

【问题讨论】:

    标签: node.js express mocha.js sinon proxyquire


    【解决方案1】:

    您可以使用sinon 来存根isAuthenticated 方法,但您应该在将auth.isAuthenticated 的引用设置为中间件之前执行此操作,因此在您需要index.jsapp 之前创建。您很可能希望在 beforeEach 挂钩中使用它:

    var app;
    var auth;
    
    beforeEach(function() {
      auth = require('../wherever/auth/auth.service');
      sinon.stub(auth, 'isAuthenticated')
          .callsFake(function(req, res, next) {
              return next();
          });
    
      // after you can create app:
      app = require('../../wherever/index');
    });
    
    afterEach(function() {
      // restore original method
      auth.isAuthenticated.restore();
    });
    
    it('it should return a 200 response', function(done) {
      request(app).post('/subscriptions/sync')
      .set('Authorization','Bearer '+ authToken)
      .send({receipt: newSubscriptionReceipt })
      .expect(200,done);
    });
    

    请注意,即使auth.isAuthenticated 恢复后,现有的app 实例也会有存根作为中间件,因此如果您出于某种原因需要获得原始行为,则需要创建另一个app 实例。

    更新:有一种方法可以改变中间件的行为,而无需每次都重新创建服务器,如 another SO answer 中所述。

    【讨论】:

    • 我遇到了类似的问题,感觉这个解决方案应该对我有用,但我的还是坏了。对这个类似的问题有什么想法吗? stackoverflow.com/questions/53852873/…
    • @LukeSchlangen 在那里发布了答案
    • @SergeyLapin 有没有办法使用Sinon来模拟参数化中间件?中间件定义如下:exports.authUser = function (options) { return function (req, res, next) { // 根据选项对象实现中间件函数 next() } }
    • @hareshhanat 当然,我相信同样的方式,只需要返回中间件而不是将其传递给callsFake:sinon.stub(authModule, 'authUser') .callsFake((options) => ( req, res, next) => { return next(); });
    • @SergeyLapin 是的,明白了。非常感谢!!
    猜你喜欢
    • 2020-08-13
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    • 2016-04-04
    • 2011-08-08
    • 2019-08-17
    • 2012-11-14
    • 1970-01-01
    相关资源
    最近更新 更多