我正在尝试模拟对JSONP GET请求的响应,该请求是使用一个返回ES6保证的函数创建的,该保证已包含在$q.when()
中。代码本身工作得很好,但是,在单元测试中,请求没有被$ httpBackend捕获并直接进入实际的URL。因此,当调用flush()
时,我收到一条错误,指出Error: No pending request to flush !
。 JSONP请求是通过ES6承诺中的jQuery $.getJSON()
进行的,因此我选择通过提供正则表达式而不是硬编码URL来尝试捕获所有传出请求。
我一直在寻找现在已经有一段时间想出这个问题了,但仍然没有理解是什么导致这个电话通过。我觉得好像ES6承诺中的HTTP请求是“在Angular之外”,因此$ httpBackend不知道它/无法捕获它,尽管如果正在进行调用可能不是这种情况从一开始就在一个$ q的承诺里面。任何人都可以告诉我为什么这个电话会通过,为什么一个简单的超时工作正常?我在这里尝试了$scope.$apply
,$scope.$digest
和$httpBackend.flush()
的所有组合,但无济于事。
也许有些代码会更好地解释它......
控制器
function homeController() {
...
var self = this;
self.getData = function getData() {
$q.when(user.getUserInformation()).then(function() {
self.username = user.username;
});
};
}
单元测试
...
beforeEach(module('home'));
describe('Controller', function() {
var $httpBackend, scope, ctrl;
beforeEach(inject(function(_$httpBackend_, $rootScope, $componentController) {
$httpBackend = _$httpBackend_;
scope = $rootScope.$new(); // used to try and call $digest or $apply
// have also tried whenGET, when('GET', ..), etc...
$httpBackend.whenJSONP(/.*/)
.respond([
{
"user_information": {
"username": "TestUser",
}
}
]);
ctrl = $componentController("home");
}));
it("should add the username to the controller", function() {
ctrl.getData(); // make HTTP request
$httpBackend.flush(); // Error: No pending request to flush !
expect(ctrl.username).toBe("TestUser");
});
});
...
出于某种原因,这有效:
it("should add the username to the controller", function() {
ctrl.getData(); // make HTTP request
setTimeout(() => {
// don't even need to call flush, $digest, or $apply...?
expect(ctrl.username).toBe("TestUser");
});
});
答案 0 :(得分:0)
感谢格雷厄姆的评论,由于我对一些事情缺乏了解,我被带到了另一个不同的兔子洞,以防万一有人在同样的情况下结束...
我没有尝试使用jasmine-ajax,而只是在jQuery的getJSON上设置间谍并返回模拟响应。这最终发送了对ES6承诺的模拟响应,但由于某种原因,包装ES6承诺导致的$ q promise对象的then
函数没有被调用(也没有任何其他错误处理函数) ,甚至finally
)。我也尝试在$scope.$apply()
几乎任何地方调用 ...
spyOn($, 'getJSON').and.callFake(function (url, success) {
success({"username": "TestUser"}); // send mock data
});
ctrl.getData(); // make GET request
...
,但是无济于事。
基本实施(单元测试中):
// user.getUserInformation() returns an ES6 promise
$q.when(user.getUserInformation()).then(function() {
// this was never being called / reached! (in the unit tests)
});
问题(在控制器的来源中):
then
最终,我使用了#2的实现来发送数据,并在超时内将断言包装在单元测试中,没有指定持续时间。我意识到这不是最佳的,并且希望它不应该如何完成,但经过几个小时的努力,我已达到极限并放弃了。如果有人知道如何改进这一点,或者为什么 ...
ctrl.getData(); // make GET request
setTimeout(() => {
expect(ctrl.username).toBe("TestUser"); // works!
});
没有被召唤,我真诚地希望听到它。
单元测试:
export default Test;