[英]How to stub express middleware using sinon in typescript?
I'm trying to write an integration test for my express router using typescript, mocha, sinon and chai-http.我正在尝试使用 typescript、mocha、sinon 和 chai-http 为我的快速路由器编写集成测试。 This router uses a custom middleware that I wrote which checks for JWT in the header.该路由器使用我编写的自定义中间件,用于检查 header 中的 JWT。
Ideally, I want to stub my authMiddleware
so that I can control its behaviour without actually providing valid/invalid JWT for every test case.理想情况下,我想存根我的authMiddleware
以便我可以控制它的行为,而无需为每个测试用例实际提供有效/无效的 JWT。
When I try to stub authMiddleware
in my tests, I realised that express app
uses the actual implementation of authMiddleware
rather than mocked one.当我尝试在我的测试中存根authMiddleware
时,我意识到 express app
使用authMiddleware
的实际实现而不是模拟一个。
I've tried to import app
after mocking authMiddleware
using dynamic imports of typescript but it didn't work also.我尝试使用 typescript 的动态导入在 mocking authMiddleware
之后导入app
,但它也不起作用。
authMiddleware.ts authMiddleware.ts
import { Request, Response, NextFunction } from 'express'; export default class AuthMiddleware { verifyToken(req: Request, res: Response, next: NextFunction):void { console.log('Actual implemetation of verifyToken is called;'); // verify token next(); } }
subjectRouter.ts主题路由器.ts
import express from'express'; import AuthMiddleware from '../middleware/authMiddleware'; import * as subjectController from '../controller/subjectController'; const router = express.Router(); const authMiddleware = new AuthMiddleware(); router.post('/', authMiddleware.verifyToken, subjectController.createSubject); export default router;
app.ts应用程序.ts
import express from 'express'; import subjectRoute from './route/subjectRoute'; // Initilize express app const app = express(); app.set("port", 3000); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); // Routers app.use('/user', userRoute); app.use('/subject', subjectRoute); export default app;
subjectTests.ts主题测试.ts
import app from '../../src/app'; import AuthMiddleware from '../../../src/middleware/AuthMiddleware'; describe('Subject', () => { let app; beforeEach(async () => { sinon.stub(AuthMiddleware.prototype, 'verifyToken').callsFake((req: Request, res: Response, next: NextFunction): void => { console.log('Fake verifyToken is called;'). // THIS IS NEVER CALLED IN TESTS..; }). app = (await import('../../../src/app'));default; }), it('should throw 403 when jwt is missing in header'. (done) => { request(app).post(/subject),end((err. res) => { expect(res).has;status(403); done(); }); }); });
When I run the above test I see that mock authMiddleware
is not called.当我运行上述测试时,我看到没有调用模拟authMiddleware
。 app
in tests uses the real implementation of authMiddleware
object.测试中的app
使用authMiddleware
object 的真实实现。
Is there a way to stub express middleware and pass it to app explicitly?有没有办法存根 express 中间件并将其显式传递给应用程序?
I've just explained what is happening in this response , however giving only workaround.我刚刚解释了此响应中发生的情况,但仅提供了解决方法。
After few thoughts, i believe the best way to overcome this is to remove global state from your modules and capture whole initialization code into explicitly called functions (or classes, if you like), so you can create your server for each tests.经过一番思考,我认为克服这个问题的最佳方法是从模块中删除全局 state 并将整个初始化代码捕获到显式调用的函数(或类,如果你愿意)中,这样你就可以为每个测试创建服务器。 Namely, change your architecture to:即,将您的架构更改为:
// router.ts
export function createRouter() {
/// ...
router.post('/', authMiddleware.verifyToken, subjectController.createSubject);
return router;
}
// app.ts
import { createRouter} from "./router.js"
export function createApp() {
///same code as currently, but in function
app.use('/subject', createRouter());
}
Now, you can create new "app" in each setup callback:现在,您可以在每个设置回调中创建新的“应用程序”:
// test.ts
beforeEach(async () => {
sinon.stub(AuthMiddleware.prototype, 'verifyToken').callsFake((req: Request, res: Response, next: NextFunction): void => {
...
});
app = (await import('../../../src/app')).createApp(); // note that we create new app for each test, so you're not polutting global state of app
});
This approach has many advantages, among others:这种方法有很多优点,其中包括:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.