如何从AngularJS控制器测试返回值的承诺茉莉? [英] How to Test Value Returned in Promise from AngularJS Controller with Jasmine?
问题描述
我有一个公开,返回休息后,调用一些文本功能的控制器。它工作正常,但我有麻烦茉莉花测试。 承诺处理程序中的code在测试中从未执行
控制器:
/ *全球Q * /
使用严格的;
angular.module(MyModule的',['some.service'])
.controller('MyCtrl',['$范围,SomeSvc',函数($范围,SomeSvc){ $ scope.getTheData =功能(ID){
VAR递延= Q.defer();
VAR processedResult ='';
SomeSvc.getData(id)的
。然后(功能(结果){
//处理数据
processedResult ='一些东西';
deferred.resolve(processedResult);
})
.fail(功能(错误){
deferred.reject(ERR);
});
返回deferred.promise;
}
}]);
测试:
描述(有些测试',函数(){
变量$范围;
变量$控制器;
变量$ httpBackend;
beforeEach(函数(){
模块('Mymodule中');
注(功能(_ $ rootScope_,_ $ controller_,_ $ httpBackend_){
。$ SCOPE = _ $ rootScope _ $新();
$控制器= _ $ controller_;
$ httpBackend = _ $ httpBackend_;
//嘲笑调用来自控制器的SomeSvc通话将
$ httpBackend.expect('GET','在/ URL /到/我/数据);
$ httpBackend.whenGET(简称/ URL /到/我/数据)
.respond({数据:大量的数据'});
$控制器('MyCtrl',{
$范围:$范围
});
});
}); 描述(测试自许返回值',函数(){
VAR舞会= $ scope.getTheData(someId);
prom.then(功能(结果){
预期(结果).toBe(意料中事); //这个code从不运行
})
});
});
我会做的是使用间谍的成功和失败的回调,并期望成功回调已经调用所需的数据。
在中的任何内容,然后
将不会被运行,除非承诺回调被称为 - 这是你的风险。 测试将自期望从未运行。传递所以不要使用期望
在然后
在测试中。手摇一切来代替。使用 $ httpBackend.flush()
, $ timeout.flush()
,范围。$适用于()
,其中需要得到控制器/服务去的一步的。这使你可以看到,国家就是你希望它是变更后/前的东西。
因为你可能想测试阴性结果为好,最好是使用 $ httpBackend.expectGet()。响应()
和 $ httpBackend .flush()
比 whenGet()
。这样,您就可以测试被拒绝的值也是一个新的测试是正确的。 刷新
将触发消化周期都优秀的请求接收数据。
whenGet / whenPost是最好的一个mockServer模块,这样就可以不用服务器运行应用程序(应该可以提出请求任意次数)。
试试这个退出
描述('MyCtrl.getData',函数(){
VAR
$范围;
$控制器;
$ httpBackend; beforeEach(函数(){
模块('Mymodule中');
注(功能(_ $ rootScope_,_ $ controller_,_ $ httpBackend_){
。$ SCOPE = _ $ rootScope _ $新();
$控制器= _ $ controller_;
$ httpBackend = _ $ httpBackend_;
$控制器('MyCtrl',{
$范围:$范围
});
}); 它('应通过承诺成功返回的数据',函数(){
VAR
数据= {数据:大量数据},
successSpy = jasmine.createSpy(成功),
failureSpy = jasmine.createSpy(失败); $ scope.getTheData(someId)。然后(successSpy,failureSpy); 。$ httpBackend.expect('GET','在/ URL /到/我/数据)响应(200,数据);
$ httpBackend.flush(); 期待(successSpy).toHaveBeenCalledWith(数据);
期待(failureSpy).not.toHaveBeenCalled();
}); 它('应通过承诺如果服务器坏了拒绝数据',函数(){
VAR
successSpy = jasmine.createSpy(成功),
failureSpy = jasmine.createSpy(失败); $ scope.getTheData(someId)。然后(successSpy,failureSpy); $ httpBackend.expect('GET','在/ URL /到/我/数据)响应(500)。
$ httpBackend.flush(); 期待(successSpy).not.toHaveBeenCalled();
期待(failureSpy).toHaveBeenCalled();
});
});
I have a controller that expose a function that returns some text after a rest call. It works fine, but I'm having trouble testing it with Jasmine. The code inside the promise handler in the test never executes.
The controller:
/* global Q */
'use strict';
angular.module('myModule', ['some.service'])
.controller('MyCtrl', ['$scope', 'SomeSvc', function ($scope, SomeSvc) {
$scope.getTheData = function (id) {
var deferred = Q.defer();
var processedResult = '';
SomeSvc.getData(id)
.then(function (result) {
//process data
processedResult = 'some stuff';
deferred.resolve(processedResult);
})
.fail(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
}]);
The test:
describe('some tests', function() {
var $scope;
var $controller;
var $httpBackend;
beforeEach(function() {
module('myModule');
inject(function(_$rootScope_, _$controller_, _$httpBackend_) {
$scope = _$rootScope_.$new();
$controller = _$controller_;
$httpBackend = _$httpBackend_;
//mock the call that the SomeSvc call from the controller will make
$httpBackend.expect('GET', 'the/url/to/my/data');
$httpBackend.whenGET('the/url/to/my/data')
.respond({data:'lots of data'});
$controller ('MyCtrl', {
$scope: $scope
});
});
});
describe('test the returned value from the promise', function() {
var prom = $scope.getTheData(someId);
prom.then(function(result) {
expect(result).toBe('something expected'); //this code never runs
})
});
});
What I would do is to use a spy for the success and failure callbacks, and expect the success callback to have been called with the data you expect.
Anything inside a then
will not be run unless the promise callbacks are called - which is a risk for you. The test will pass since the expect was never run. So don't use expect
inside then
in tests. Hand crank everything instead. Use $httpBackend.flush()
, $timeout.flush()
, scope.$apply()
where needed to get the controller/services to go one step further. This let's you see that the state is what you want it to be before/after the change.
Since you might want to test negative results as well, it's better to use $httpBackend.expectGet().respond()
and $httpBackend.flush()
than whenGet()
. This way you can test that the rejected value is also correct in a new test. flush
will trigger a digest cycle and have all outstanding requests receive their data.
whenGet/whenPost is best for a mockServer module, so that you can run your application without a server (should be possible to make a request any number of times).
Try this out
describe('MyCtrl.getData', function() {
var
$scope;
$controller;
$httpBackend;
beforeEach(function() {
module('myModule');
inject(function(_$rootScope_, _$controller_, _$httpBackend_) {
$scope = _$rootScope_.$new();
$controller = _$controller_;
$httpBackend = _$httpBackend_;
$controller ('MyCtrl', {
$scope: $scope
});
});
it('should return data successfully through promise', function() {
var
data = { data: 'lots of data' },
successSpy = jasmine.createSpy('success'),
failureSpy = jasmine.createSpy('failure');
$scope.getTheData(someId).then(successSpy, failureSpy);
$httpBackend.expect('GET', 'the/url/to/my/data').respond(200, data);
$httpBackend.flush();
expect(successSpy).toHaveBeenCalledWith(data);
expect(failureSpy).not.toHaveBeenCalled();
});
it('should reject data through promise if the server is broken', function() {
var
successSpy = jasmine.createSpy('success'),
failureSpy = jasmine.createSpy('failure');
$scope.getTheData(someId).then(successSpy, failureSpy);
$httpBackend.expect('GET', 'the/url/to/my/data').respond(500);
$httpBackend.flush();
expect(successSpy).not.toHaveBeenCalled();
expect(failureSpy).toHaveBeenCalled();
});
});
这篇关于如何从AngularJS控制器测试返回值的承诺茉莉?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!