如何在angular js测试中指定http响应顺序
How to specify http response order in angular js tests?
控制器对远程http位置进行2次调用以获取数据。当数据到来时,一个过程被调用。当两个请求都返回数据时,则完成数据合并并执行一些聚合。
单元测试的目的是测试无论响应的顺序如何,控制器是否按预期工作。
it("downloads all data and combines it", function() {
...
$httpBackend.expectGET(responsePerDomainQuery).respond(
{ result: [ { result: 2 }, { result: 3 } ] });
$httpBackend.expectGET(responsePerTrQuery).respond(
{ result: [{ result: 1 }, { result: 4 }] });
$controller("Ctrl", { '$scope': $scope });
$httpBackend.flush();
... some expectations ...
}
测试通过了,但它不能保证任何成功响应请求的顺序都不会破坏控制器的逻辑。如何才能做到这一点?
当我说"不需要测试这种情况"时,我指的是使用$q.all
已经保证只有在所有请求都满足时才执行回调的事实。话虽如此,我同意为自己的实现准备测试是一种很好的实践,所以我要这样做。
(注意这只是伪代码,有些东西可能需要调整才能正常工作,但这只是为了解释我将如何解决这个问题。)
首先,我会将AJAX调用从控制器移开,并为它们提供专门的服务(也许您已经这样做了,如果这样很好,请先听我说)。
例如:
angular.service('myQueries', function($http){
this.myReq1 = function(){
return $http.get(API.url1);
};
this.myReq1 = function(){
return $http.get(API.url2);
};
});
然后我将使用$httpBackend.expectGET()
单独测试此服务。
然后我将返回控制器并使用在我对问题的评论中指定的服务:
angular.controller('myCtrl', function($scope, myQueries, $q){
// at load time query for results
$q.all([myQueries.myReq1(), myQueries.myReq2()])
// everything after this is guaranteed to be run ONLY when
// both responses are in our hands
.then(doSomethingWithBoth)
// one or both requests went bad
// let's handle this situation too.
.catch(someThingWentBad);
function doSomethingWithBoth(data){
$scope.myData = data;
}
function someThingWentBad(data){
$scope.disaster = true;
}
});
此时,我们可以测试我们的控制器并向其注入一个模拟服务。有很多方法,但应该做类似的事情:
var scope, controller, fakeService, q, dfd1, dfd2;
beforeEach(function(){
fakeService = {
myReq1: function(){
dfd1 = q.defer();
return dfd1.promise;
},
myReq2: function(){
dfd2 = q.defer();
return dfd2.promise;
},
};
})
beforeEach(inject(function ($rootScope, $controller, $q) {
q = $q;
scope = $rootScope.$new();
controller = $controller('myCtrl', { $scope: scope, myQueries: fakeService });
}));
在这一点上,你可以自由地解决/拒绝承诺,当你想要的。您可以检查当第一个响应比第二个响应快时会发生什么:
it('should do this when one response is faster', function(){
dfd1.resolve('blabla');
// myReq2 is still pending so doSomethingWithBoth() has not yet been called
scope.$apply();
expect(scope.myData).toBe(undefined);
dfd2.resolve('i am late, sorry');
scope.$apply();
expect(scope.myData).not.toBe(undefined);
});
您可以检查当第二个响应比第一个响应快时会发生什么:
it('should do this when the other response is faster', function(){
dfd2.resolve('here is a response');
// myReq1 is still pending so doSomethingWithBoth() has not yet been called
scope.$apply();
expect(scope.myData).toBe(undefined);
dfd1.resolve('i am late, sorry');
scope.$apply();
expect(scope.myData).not.toBe(undefined);
});
或者当其中一个失败时会发生什么:
it('should do this when one response fails', function(){
dfd1.resolve('blabla');
dfd2.reject();
scope.$apply();
expect(scope.disaster).toBeTruthy();
});
我们可以使用这样的东西alpha var将从第一次调用中获得响应,例如....
var promiseAlpha= $http({method: 'GET', url: 'a/pi-one-url', cache: 'true'});
var promiseBeta= $http({method: 'GET', url: '/api-two-url', cache: 'true'});
let promises = {
alpha: promiseAlpha,
beta: promiseBeta
}
$q.all(promises).then((values) => {
console.log(values.alpha); // value alpha
console.log(values.beta); // value beta
console.log(values.gamma); // value gamma
complete();
});
相关文章:
- IIS动态HTTP响应标头
- 我如何设置HTTP头“;访问控制允许起源”;用于来自thttpd web服务器的HTTP响应
- Http响应拆分安全问题的XMLHTTPRequest/Response用例的Filter实现
- 使用Express筛选HTTP响应
- 使用不同参数的超级代理缓存缓存 HTTP 响应
- 如何无限期缓存HTTP响应
- 如果HTTP响应为404,脚本标记会被阻塞吗
- Angular 2:用HTTP响应填充复选框列表
- 如何访问您没有访问的HTTP响应的标头't使用javascript通过AJAX发送
- string http响应!=javascript中的相同字符串
- 拦截$resource和$http响应angular
- HTTP响应中出现意外内容
- 如何在java脚本中从http响应生成blob
- 如何记录Apache Cordova应用程序中加载的iframe的http响应
- 如何缓存$http响应以便在angularjs中重用
- 如何将$http响应值传递给另一个函数
- 检查 http 响应代码以显示相应的失败消息
- $http响应拦截器标头
- 在封闭的 python 服务器上的 ajax 请求中获取 0 作为 Http 响应代码
- 如何正确编写 http 响应以便使用 XHR 进度事件侦听器