javascript - Node / Express / Mocha 禁用中间件?
问题描述
我有一个看起来像这样的 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 进行单元测试,我发现的每一个资源似乎都是功能测试,提出了一个真正的请求......
解决方案
如果您的环境是测试、生产或开发,您可以在应用程序中使用环境变量指定。从中间件写条件是这样的
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 请求即可轻松测试。