【发布时间】:2016-12-03 15:05:57
【问题描述】:
我正在尝试模拟对 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");
});
});
【问题讨论】:
-
httpBackend 是一个模拟实现,它通过角度注入到 $http 服务中进行单元测试,如果您不使用 $http 服务发出请求,您将无法使用 httpBackend 捕捉它
标签: javascript angularjs ajax unit-testing jasmine