当前位置: 首页 > 知识库问答 >
问题:

如何在typescript中使用sinon存根表示中间件?

劳和雅
2023-03-14

我正在尝试使用typescript、mocha、sinon和chai http为我的express路由器编写一个集成测试。这个路由器使用我编写的自定义中间件,它检查头中的JWT。

理想情况下,我想存根我的authMiddleware,这样我就可以控制它的行为,而不必为每个测试用例提供有效/无效的JWT。

当我尝试在测试中存根AuthMiddleware时,我意识到Expressapp使用AuthMiddleware的实际实现,而不是模拟的实现。

在模拟authMiddleware之后,我尝试使用typescript的动态导入导入应用程序,但也没有成功。

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();
    }
}

主题路由器。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;

应用程序。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;

受试者测试。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();
            });
    });
});

当我运行上述测试时,我看到没有调用mockauthMiddleware<测试中的代码>应用程序使用authMiddleware对象的实际实现。

有没有办法存根Express中间件并将其显式传递给应用程序?


共有1个答案

柳钟展
2023-03-14

我刚刚解释了此响应中发生的情况,但只给出了解决方法。

经过一些思考,我相信克服这个问题的最佳方法是从您的模块中删除全局状态并将整个初始化代码捕获到显式调用的函数(或类,如果您愿意)中,这样您就可以为每个测试创建您的服务器。也就是说,将您的架构更改为:

// 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());
}

现在,您可以在每个设置回调中创建新的“应用程序”:

// 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
});

这种方法有许多优点,其中包括:

  • 您可以为不同的测试模拟不同的函数;
  • 您正在有效地从代码中删除“隐式单例”,这些代码的存在是您问题的根本原因。
 类似资料:
  • 我试图为express中间件功能设置存根伪造,但它并没有被取代。 我正试图通过callsFake函数使用sinon stubbing,正如他们最新文档中建议的那样。 即使我需要模块并在导出时替换属性中的函数。我一直看到原来的函数行为在起作用。 我知道我应该在安装中间件函数之前尝试将函数存根,而这正是第一次导入express的时候。 这是我尝试存根的函数,定义为函数并导出为对象。它在脚本文件中定义,

  • 我想知道我是否缺少关于sinon.js的任何信息,我尝试使用sinon.stub()。返回和收益率,但无法得到结果。任何指针都将有所帮助。 我有一个模块,它调用另一个从数据库返回值的模块 我使用mocha作为测试框架,也使用sinon。我面临的问题是,当我创建一个users.findOne存根以返回一个值时,控件不会到达我的else if(用户)条件。 我的单元测试案例如下

  • 如果我已经通过< code > var a = sinon . createstuinstance(my contractor)创建了一个实例。 如何替换其中一个存根函数,如 。 我这样做的主要原因是想实现这个提到的多个回调解决方法

  • 我在获取一个sinon存根以返回/解析另一个sinon存根时遇到问题。我正在使用西农、柴、柴和摩卡。 我正在按顺序执行许多异步任务,我想测试的代码看起来像这样: 我尝试为此创建存根的尝试如下所示: “saveit”方法在Terminal.prototype,这就是为什么我需要在那里存根它。当我尝试运行它时,我收到错误消息: 在线上: 但如果我在控制台中转储终端对象,它看起来很好,就像任何其他存根对

  • 我想验证各种日期字段是否被正确更新,但我不想在预测< code>new Date()何时被调用上浪费时间。我如何剔除日期构造函数? 如果相关,这些测试在节点应用程序中运行,我们使用TypeScript。

  • 问题内容: 我正在尝试测试特定路线的行为。即使我创建存根,它也会继续运行中间件。我希望事件认证暂时通过。我了解到,这并不是真正的“单元”测试。我快到那里了。我还简化了代码。这是要测试的代码: 这是我要跳过的中间件: 测试文件: 我尝试过其他类似的问题,但是我仍然从中间件中获取403,应该跳过它。我还以调试模式运行测试,因此我知道应该存根的中间件功能仍在运行。 这是存根我的代码的问题吗?这是ES6问