首页 > 解决方案 > 从 http 调用调用检查中间件

问题描述

如何测试一个自定义中间件实际上是从标准 HTTP 事件中调用的?

IE。中间件从以下位置调用:

MyController.js

router.get('/some/endpoint', [myMiddleware()], (req, res, next) => {
    // Code to do whatever here
});

中间件本身可以定义为:

MyMiddleware.js

module.exports = () => {
    // Middleware code in here
}

我的任务是检查是否从我的单元测试中调用了一次中间件,但我找不到与此相关的文档。

MyTest.test.js

it('Should return whatever from GET call', () => {
    return request(app).get('/some/endpoint')
        .expect(200)
        .expect(res => {res.body.should.deep.equal(bodyValue)});
    // How would I place code in here to check that MyMiddleware is called? 
    // ie. sinon.assert.calledOnce(MyMiddleware)
});

有想过用诗乃的spy,但是想不出怎么挂钩中间件……我的尝试是这样的:

const mwSpy = sinon.spy(require('path to middleware file'));

sinon.assert(calledOnce(mwSpy));

标签: unit-testingexpressmiddlewaresinonsinon-chai

解决方案


解决这个问题的通常方法是将其分为两个测试,一个集成测试和一个单元测试。

  1. 当有人点击此端点时,我在router.get调用中指定的中间件最终会被调用吗?
  2. 我的中间件做对了吗?

第一部分基本上是测试 Express API 是否按照文档所述执行。这不是单元测试的用途(这已被标记unit-testing),但由于您已经在使用 HTTP 请求来测试端点,我想这不是您所追求的:您基本上是在为您的系统创建验证测试。

不过,您仍然可以在没有 HTTP 的情况下测试 Express 路由,正如我在对这个问题的回答中详细说明的那样,关于如何以编程方式测试路由器(更快的测试,没有 http),但更少坚持您所拥有的。

所以基本问题是:“我的任务是检查中间件是否从我的单元测试中调用过一次”。您似乎并不关心中间件是否在做正确的事情,只是它被调用了,这引发了我们是否应该测试中间件或使用中间件的层的问题。

在这两种情况下,您都需要找到一种注入测试间谍的方法。要么您编写一个小的实用程序方法来注入该间谍:function setMiddleware(module){ middleware = module; }要么您使用一些工具,例如proxyquire. 有关背景,请参阅诗乃主页上的本教程

我会这样做(在测试代码中):

it('Should return whatever from GET call', () => {
  var middlewareFake = sinon.fake();
  // I am assuming it's the actual app object you are referencing below in the request(app) line
  var app = proxyquire('../app/index.js', { './my-middleware': middlewareFake });

  //
  return request(app).get('/some/endpoint')
    .expect(200)
    .expect(res => {
      res.body.should.deep.equal(bodyValue)

      expect(middlewareFake).was.called;
    });
});

推荐阅读