我正在尝试确保我的单元测试用例涵盖承诺永远不会解决的场景,并且我遇到了一些问题。
一个代码块胜过千言万语,所以..
it('returns my resource', function() {
var myUser = {name:'Bob'}
$httpBackend.expectGET('/myresource').respond(200,myUser);
myService.getMyUser()
.then(function(data) {
expect(data).toEqual(myUser);
},fail);
});
这一切都很好,并且测试响应是否符合预期,如果承诺被拒绝,测试也失败。
但是,如果承诺永远不会得到解决,测试就会通过,我希望它失败。我在myService中缓存此请求,如下所示:
var cachedUser;
function getMyUser(forceUpdate) {
var deferred = $q.defer();
if (cachedUser && !forceUpdate) {
deferred.resolve(cachedUser);
} else {
$http.get('/myresource')
.then(function(data) {
cachedUser = data;
deferred.resolve(data);
},function(error) {
deferred.reject(error);
});
}
return deferred.promise;
}
现在在上面的场景中,如果要从$http.get中删除行"deferred.resolve(data)
",测试仍然会通过。 这是因为包含data.toEqual(myUser)
期望的回调函数永远不会运行。 但是,测试应该失败,因为删除该行会破坏此函数的目的。
我已经尝试在测试代码中使正回调成为间谍并期望间谍 HaveBeenCalled,但这似乎在承诺解决之前运行并且失败,即使我可以看到间谍的功能通过控制台日志运行。
我也尝试在单元测试中将承诺放入变量中,然后expect(promise.$$state.status).toEqual(1)
,但似乎在解决承诺之前运行了这个期望,因此测试在应该通过时失败。
在回答之前,请确保您了解问题,如果我不清楚,请发表评论。
问题原来是,在处理$httpBackend时,您必须刷新()后端才能使请求通过。 我在每个测试周围的afterEach()
块中执行此操作,因此当尝试从测试块内测试承诺的状态时,承诺实际上尚未解决。
通过将$httpBackend.flush()
移动到单元测试中,返回的承诺确实将其状态从 0 更新为 1。
以下是最终的单元测试代码:
it('returns my resource', function() {
var myUser = {name:'Bob'}
var promise;
$httpBackend.expectGET('/myresource').respond(200,myUser);
promise = myService.getMyUser()
.then(function(data) {
expect(data).toEqual(myUser);
},fail);
$httpBackend.flush();
expect(promise.$$state.status).toEqual(1);
});