我正在使用 ngMock 进行单元测试,我需要在其中一个测试中使用 $timeout.flush 函数,因此我在测试中添加了以下两行:
$timeout.flush();
$timeout.verifyNoPendingTasks();
如http://www.bradoncode.com/blog/2015/06/11/unit-testing-code-that-uses-timeout-angularjs/所示。
$timeout.flush() 确实按预期刷新超时,但是我现在每次运行测试时都会从 angular-mocks.js 中得到一个异常:
日志:'异常:',错误{行:1441,sourceURL:' http://localhost:9876/base/node_modules/angular-mocks/angular-mocks.js?05a191adf8b7e3cfae1806d65efdbdb00a1742dd ',堆栈:'$httpBackend@ http:// /localhost:9876/base/node_modules/angular-mocks/angular-mocks.js?05a191adf8b7e3cfae1806d65efdbdb00a1742dd:1441:90 ....
全局代码@ http://localhost:9876/context.html:336:28 '}, '原因:',未定义
有谁知道这个异常可能来自哪里?我得到它的次数与使用 $timeout.flush() 函数的次数一样多。
查看 angular-mocks.js 文件,它看起来像是来自 $httpBackend 函数。我试图更新 ngMock 版本,但它没有改变任何东西。我已经尝试了 1.4.7 版(这是我的 Angular 版本)和 1.6.2 版。
function $httpBackend(method, url, data, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) {
var xhr = new MockXhr(),
expectation = expectations[0],
wasExpected = false;
xhr.$$events = eventHandlers;
xhr.upload.$$events = uploadEventHandlers;
function prettyPrint(data) {
return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
? data
: angular.toJson(data);
}
function wrapResponse(wrapped) {
if (!$browser && timeout) {
if (timeout.then) {
timeout.then(handleTimeout);
} else {
$timeout(handleTimeout, timeout);
}
}
return handleResponse;
function handleResponse() {
var response = wrapped.response(method, url, data, headers, wrapped.params(url));
xhr.$$respHeaders = response[2];
callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders(),
copy(response[3] || ''));
}
function handleTimeout() {
for (var i = 0, ii = responses.length; i < ii; i++) {
if (responses[i] === handleResponse) {
responses.splice(i, 1);
callback(-1, undefined, '');
break;
}
}
}
}
if (expectation && expectation.match(method, url)) {
if (!expectation.matchData(data)) {
throw new Error('Expected ' + expectation + ' with different data\n' +
'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
}
if (!expectation.matchHeaders(headers)) {
throw new Error('Expected ' + expectation + ' with different headers\n' +
'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
prettyPrint(headers));
}
expectations.shift();
if (expectation.response) {
responses.push(wrapResponse(expectation));
return;
}
wasExpected = true;
}
var i = -1, definition;
while ((definition = definitions[++i])) {
if (definition.match(method, url, data, headers || {})) {
if (definition.response) {
// if $browser specified, we do auto flush all requests
($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
} else if (definition.passThrough) {
originalHttpBackend(method, url, data, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers);
} else throw new Error('No response defined !');
return;
}
}
throw wasExpected ?
new Error('No response defined !') :
new Error('Unexpected request: ' + method + ' ' + url + '\n' +
(expectation ? 'Expected ' + expectation : 'No more request expected'));
}