在不创建重新创建服务器的情况下测试 Express 中间件的简单方法?
Simple way to test middleware in Express without creating recreating server?
我希望能够在每次测试的基础上存根我的中间件函数。正如所述,问题是我不能只存根我的中间件函数,因为节点已经缓存了中间件函数,所以我不能存根,因为我在一开始就创建了我的应用程序。
const request = require("supertest");
const { expect } = require("chai");
const sinon = require('sinon');
const auth = require ("../utils/auth-middleware")
const adminStub = sinon.stub(auth, "isAdmin").callsFake((req, res, next) => next());
const app = require("../app.js"); // As soon as I create this, the middleware isAdmin function becomes cached and no longer mutable
以上作为链接的 SO 答案中描述的解决方案,但我不喜欢那样为了恢复存根或修改假的,我必须完全重新创建服务器。
我想知道是否有更好、更优雅的方法来解决 Node 首先缓存这些函数的事实 require
。我正在考虑使用 proxyquire
或 decache
,但两者似乎都提供了解决方法而不是可持续的解决方案(尽管我在这里很可能是错误的)。
这个问题与 Node 缓存模块并没有真正的关系 - 它是在最初创建服务器时存储对中间件函数的引用的明确表示。
在 require
d 模块的 isAdmin
方法被存根后,它是被存根的缓存版本,所以使用像 proxyquire
这样的工具只允许你需要一个新版本的模块(没有存根方法)如果你出于某种原因需要它。
如果您正在寻找的是为已创建的快速服务器调整特定中间件的行为,您需要一种方法来通过其引用来更改中间件功能的行为。
希望 sinon 存根(以及其他存根,例如开玩笑提供的存根)能够做到这一点。但是,您仍然需要在创建快速服务器之前存根模块,以便它存储对存根函数的引用。
示例实现可能如下所示:
const request = require("supertest");
const { expect } = require("chai");
const sinon = require('sinon');
const auth = require ("../utils/auth-middleware");
// store reference to original function in case you need it:
const originalIsAdmin = auth.isAdmin
// replace isAdmin method with a stubbed, but don't specify implementation yet
const adminStub = sinon.stub(auth, "isAdmin");
// init express server that relies on stubbed `auth.isAdmin` reference
const app = require("../app.js");
it('this test is using auth.isAdmin that just calls .next()', () => {
// make middleware just pass
auth.isAdmin.callsFake((req, res, next) => next());
// ...
});
it('this test is using real auth.isAdmin implementation', () => {
// make middleware call real implementation
auth.isAdmin.callsFake(originalIsAdmin);
// ...
});
Sergey Lapin 解决方案非常适合我进行单文件测试。
如果你是 运行 多个测试文件(例如 mocha)并且其中之一像 Sergey Lapin 建议的那样对中间件进行存根 - callsFake 不起作用。
解决方法:
test_config.js
const auth= require('../utils/auth-middleware');
const sinon = require('sinon');
const originalIsAdmin = auth.isAdmin;
const stubbedIsAuth = sinon.stub(auth, 'isAdmin');
const app = require("../app.js");
module.exports = {
originalIsAdmin,
stubbedIsAuth,
app,
};
内部文件 A.js 你需要跳过的是 isAdmin:
const { app } = require('./test_config');
const auth= require('../utils/auth-middleware');
// before each test. No other .stub
beforeEach(function () {
auth.isAdmin.callsFake((req, res, next) => next());
});
内部文件 B.js 你需要 isAdmin 的原始实现的地方:
const { originalIsAdmin, app} = require('./test_config');
// before each test. No other .stub
beforeEach(function () {
auth.isAdmin.callsFake(originalIsAdmin);
});
我希望能够在每次测试的基础上存根我的中间件函数。正如
const request = require("supertest");
const { expect } = require("chai");
const sinon = require('sinon');
const auth = require ("../utils/auth-middleware")
const adminStub = sinon.stub(auth, "isAdmin").callsFake((req, res, next) => next());
const app = require("../app.js"); // As soon as I create this, the middleware isAdmin function becomes cached and no longer mutable
以上作为链接的 SO 答案中描述的解决方案,但我不喜欢那样为了恢复存根或修改假的,我必须完全重新创建服务器。
我想知道是否有更好、更优雅的方法来解决 Node 首先缓存这些函数的事实 require
。我正在考虑使用 proxyquire
或 decache
,但两者似乎都提供了解决方法而不是可持续的解决方案(尽管我在这里很可能是错误的)。
这个问题与 Node 缓存模块并没有真正的关系 - 它是在最初创建服务器时存储对中间件函数的引用的明确表示。
在 require
d 模块的 isAdmin
方法被存根后,它是被存根的缓存版本,所以使用像 proxyquire
这样的工具只允许你需要一个新版本的模块(没有存根方法)如果你出于某种原因需要它。
如果您正在寻找的是为已创建的快速服务器调整特定中间件的行为,您需要一种方法来通过其引用来更改中间件功能的行为。 希望 sinon 存根(以及其他存根,例如开玩笑提供的存根)能够做到这一点。但是,您仍然需要在创建快速服务器之前存根模块,以便它存储对存根函数的引用。
示例实现可能如下所示:
const request = require("supertest");
const { expect } = require("chai");
const sinon = require('sinon');
const auth = require ("../utils/auth-middleware");
// store reference to original function in case you need it:
const originalIsAdmin = auth.isAdmin
// replace isAdmin method with a stubbed, but don't specify implementation yet
const adminStub = sinon.stub(auth, "isAdmin");
// init express server that relies on stubbed `auth.isAdmin` reference
const app = require("../app.js");
it('this test is using auth.isAdmin that just calls .next()', () => {
// make middleware just pass
auth.isAdmin.callsFake((req, res, next) => next());
// ...
});
it('this test is using real auth.isAdmin implementation', () => {
// make middleware call real implementation
auth.isAdmin.callsFake(originalIsAdmin);
// ...
});
Sergey Lapin 解决方案非常适合我进行单文件测试。 如果你是 运行 多个测试文件(例如 mocha)并且其中之一像 Sergey Lapin 建议的那样对中间件进行存根 - callsFake 不起作用。
解决方法: test_config.js
const auth= require('../utils/auth-middleware');
const sinon = require('sinon');
const originalIsAdmin = auth.isAdmin;
const stubbedIsAuth = sinon.stub(auth, 'isAdmin');
const app = require("../app.js");
module.exports = {
originalIsAdmin,
stubbedIsAuth,
app,
};
内部文件 A.js 你需要跳过的是 isAdmin:
const { app } = require('./test_config');
const auth= require('../utils/auth-middleware');
// before each test. No other .stub
beforeEach(function () {
auth.isAdmin.callsFake((req, res, next) => next());
});
内部文件 B.js 你需要 isAdmin 的原始实现的地方:
const { originalIsAdmin, app} = require('./test_config');
// before each test. No other .stub
beforeEach(function () {
auth.isAdmin.callsFake(originalIsAdmin);
});