unit-testing - 从 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));
解决方案
解决这个问题的通常方法是将其分为两个测试,一个集成测试和一个单元测试。
- 当有人点击此端点时,我在
router.get
调用中指定的中间件最终会被调用吗? - 我的中间件做对了吗?
第一部分基本上是测试 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;
});
});
推荐阅读
- java - 多线程延迟的原因
- java - 使用 Livedata 并在显示 MutableLiveData 时遇到问题
结果 - generics - 当作为参数传递时,in/out 在 Kotlin 中实际上做了什么?
- c++ - 如何在不使用指针的情况下搜索特定字符的数组结构
- python - 管理站点中消失的蛞蝓
- android - 无法启动模拟器:错误:模拟器未在 60 秒内连接
- python - Sotfmax 的导数是否有任何适当的 numpy 函数?
- python - 如何修复 numpy python 文件加载/写入中的逻辑错误
- types - 使新的类型定义与所有模块兼容
- c++ - 无法使用 peek() 解析文本文件中的最后一个单词