【问题标题】:Node / Express / Mocha disable middleware?Node / Express / Mocha 禁用中间件?
【发布时间】:2021-03-10 16:30:49
【问题描述】:

我有一个 hello world 应用程序,如下所示:

let clientAuthMiddleware = () => (req, res, next) => {
  if (!req.client.authorized) {
    return res.status(401).send('Invalid client certificate authentication.');
  }
  return next();
};

function app() {
    const fs = require('fs');
    const https = require('https');
    const express = require('express');

    const app = express();
    app.use(clientAuthMiddleware());

    app.get('/', (req, res) => {
      console.log(req.socket.getPeerCertificate());
      return res.send('Hello world!');
    });

    https
      .createServer(
        {
          cert: fs.readFileSync('cert/localhost.crt'),
          key: fs.readFileSync('cert/localhost.key'),        
          requestCert: true,
          rejectUnauthorized: false,
          ca: fs.readFileSync('cert/ca.crt'),
        },
        app
      )
      .listen(9443);
    
    return app;
}

if (require.main === module) instance = app()
module.exports.app = app
module.exports.authMiddleware = clientAuthMiddleware

还有一个看起来像这样的测试:

 describe('GET /', function() {
    it('should return Hello world!', function(done) {
          chai.request(app.app()).get('/')
             .end((err, res) => {
                 if (err)done(err);
                 res.should.have.status(200);
                 expect(res.body).to.equal('Hello world!');
                 done();
              });
    });
  });

如何在测试中替换 authMiddleware,最好不使用一些外部存根库?有没有什么方法可以让我重新排列我的代码,所以在测试中我可以只做 app.authMiddleware = {my own stub function} 吗?

编辑:另外,有没有一种方法可以直接对这些端点进行单元测试,例如 app.get('/') 而无需发出真正的 HTTP 请求?我一直在 Google 上搜索使用 Mocha 对 Node/Express 进行单元测试,我发现的每一个资源似乎都是功能测试,提出了一个真正的请求......

【问题讨论】:

  • 如果我理解正确,您正在寻找一个可以执行 nock 的库。也许如果它符合您的需求,我可以分享一个例子。我这么说是因为你说:最好不使用一些外部存根库。
  • @Danizavtz 我对 Node 比较陌生,但我的理解是 nock 是为了模拟外部 HTTP 请求,我想测试我自己的 Express 应用程序的端点,而不需要它实际启动服务器,监听并提出真正的要求。

标签: javascript node.js express mocha.js chai


【解决方案1】:

如果您的环境是测试、生产或开发环境,您可以在应用中使用环境变量进行指定。从中间件写条件是这样的

 if(process.env.NODE_ENV !== 'test') { 
        app.use(clientAuthMiddleware()); 
 } 

如果您想在不发出 HTTP 请求的情况下测试您的应用,则需要将业务逻辑与请求处理程序分开。

例如,如果您有一个路由“/api/user/login”,那么对于该路由,您有一个类似的路由处理程序

 app.post("/api/user/login" , async (req,res) => {
    const response = await login(req.body.email,req.body.password);
    res.status(200).json(response);
 });

 // login function is independent of express 
 // routes and can be easily tested  without api requests
 async function login(email,password) {
    //login logic
 }

通过这种方式,您可以使您的业务逻辑独立于 express,并且无需 HTTP 请求即可轻松测试。

【讨论】:

  • 干杯,所以要清楚;如果不发出真正的 HTTP 请求,就无法测试实际的 Express 路由端点,即我不能将测试双重请求对象拼接在一起并直接调用 app.get?
  • 好吧,我认为没有办法在不发出 HTTP 请求的情况下测试 HTTP 端点。另一方面,将您的业务逻辑与您正在使用的框架或协议分开将是巨大的优势。您可以将 express 与 KOA 或任何其他框架交换,或者创建命令行应用程序或使用 Websockets 来完成相同的工作或测试代码单元,而无需关心 HTTP 请求,并且您不必触及业务逻辑中的任何代码行,因为你的业务逻辑和你使用的框架没有耦合,应该是这样的,希望你明白。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 1970-01-01
  • 1970-01-01
  • 2018-07-04
  • 2019-02-08
  • 2015-11-06
相关资源
最近更新 更多