【发布时间】:2020-10-27 16:00:09
【问题描述】:
我正在尝试为快速服务器建立一个测试框架,并且需要异步初始化的测试给我带来了问题。最初我尝试使用磁带和超测试,但由于磁带似乎对异步操作的整体支持很差,我改用 mocha。现在我至少收到了一些错误消息,但测试仍然无法正常工作。
我正在尝试测试一个虚拟 ping 端点 /auth_ping,它应该需要一个有效的令牌来响应 pong,否则应该响应 403。目前身份验证尚未实现,所以我正在尝试设置一个最初失败的测试,因为服务器在没有令牌的情况下响应 200 而不是 403。
我的第一次尝试是这样的
'use strict';
const request = require('supertest');
const app = require('../server');
const keycloak = require('./util/keycloak-mock');
describe("authenticated ping", function() {
it("should respond 403 when no token is provided", function(done) {
keycloak.fetchToken()
.then((token) => request(app)
.get("/auth_ping")
.expect(403)
.end(function (err, res) {
if (err) {
done(err)
};
done();
}));
});
});
测试用例从通过异步调用从模拟身份验证器获取有效令牌开始。在此测试中,未使用令牌,但我还是想进行调用以确保已初始化模拟身份验证器。无论如何,令牌会在进一步的测试用例中使用,因此获取需要工作。
我使用这个测试得到的输出如下
authenticated ping
Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises
Warning: .end() was called twice. This is not supported in superagent
superagent: double callback bug
(node:21) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected token { in JSON at position 29
at JSON.parse (<anonymous>)
at IncomingMessage.res.on (/usr/src/app/node_modules/superagent/lib/node/parsers/json.js:11:35)
at IncomingMessage.emit (events.js:203:15)
at endReadableNT (_stream_readable.js:1145:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
(node:21) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:21) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
1) should respond 403 when no token is provided
0 passing (2s)
1 failing
1) authenticated ping
should respond 403 when no token is provided:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/usr/src/app/test/index.js)
我不太确定这里的流程是如何工作的,以及为什么会发出两次请求。是的,我同时调用 then() 和 end(),但是因为 then() 与超测无关,我不知道它如何影响请求。另外 end() 似乎是我为 mocha 调用 done() 的唯一地方,所以我看不出没有它测试如何工作。
无论如何,我尝试通过删除 end() 调用来修改测试:
'use strict';
const request = require('supertest');
const app = require('../server');
const keycloak = require('./util/keycloak-mock');
describe("authenticated ping", function() {
it("should respond 403 when no token is provided", function(done) {
keycloak.fetchToken()
.then((token) => request(app)
.get("/auth_ping")
.expect(403)
);
});
});
之后的输出是这样的:
authenticated ping
(node:21) UnhandledPromiseRejectionWarning: Error: expected 403 "Forbidden", got 200 "OK"
at Test._assertStatus (/usr/src/app/node_modules/supertest/lib/test.js:268:12)
at Test._assertFunction (/usr/src/app/node_modules/supertest/lib/test.js:283:11)
at Test.assert (/usr/src/app/node_modules/supertest/lib/test.js:173:18)
at Server.localAssert (/usr/src/app/node_modules/supertest/lib/test.js:131:12)
at Object.onceWrapper (events.js:286:20)
at Server.emit (events.js:198:13)
at emitCloseNT (net.js:1619:8)
at process._tickCallback (internal/process/next_tick.js:63:19)
(node:21) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:21) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
1) should respond 403 when no token is provided
0 passing (2s)
1 failing
1) authenticated ping
should respond 403 when no token is provided:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/usr/src/app/test/index.js)
在堆栈跟踪中,我可以看到达到了预期的测试结果,因为将响应 200 与预期的 403 进行了比较,该部分现在看起来很好,但之后测试用例超时并因此而失败。我认为这是意料之中的,因为从未调用过done(),我觉得我明白这里发生了什么。
但是在我的第一次尝试中会发生什么以及如何解决这个问题?它看起来比后一种尝试更有效,但我不明白为什么请求被发送两次?
【问题讨论】:
标签: node.js asynchronous mocha.js supertest