Angular - 模拟 returns 承诺的服务方法
Angular - mocking out service method that returns a promise
我正在尝试测试依赖于服务调用来获取一些数据的控制器方法。服务方法 returns 一个承诺,如果承诺被解决或拒绝,我想测试控制器的行为。
我想出了这种方法来改变我的模拟服务方法的行为,但它不起作用。当调用模拟的 getData
方法时,getDataSuccess
标志始终为真。这是我目前所拥有的:
控制器:
app.controller('myController', function($scope, myService) {
myService.getData()
.then(function (data) {
$scope.data = data;
},
function (data) {
$scope.serverError = data;
});
});
测试:
describe('myController', function () {
var ctl, serviceMock, getDataSuccess, scope;
beforeEach(function() {
getDataSuccess = true;
serviceMock = {};
module('app', function ($provide) {
$provide.value('myService', serviceMock);
});
inject(function ($q) {
serviceMock.getData = function () {
var defer = $q.defer();
if (getDataSuccess) {
defer.resolve("theData");
} else {
defer.reject("theData");
}
return defer.promise;
};
});
});
beforeEach(inject(function ($rootScope, $controller, $httpBackend, myService) {
scope = $rootScope.$new();
ctl = $controller('myController', {
$scope: scope,
myService: myService,
});
}));
describe('myController loading data', function () {
it('should set $scope.data if data load succeeds', function () {
getDataSuccess = true;
scope.$apply();
expect(scope.data).toEqual("theData");
});
it('should set $scope.serverError if data load fails', function () {
getDataSuccess = false;
scope.$apply();
expect(scope.serverError).toEqual("theData");
});
});
});
显然我在这里遗漏了一些东西。执行顺序不是我所期望的。做这种事情的正确方法是什么?
这是 Plunker 中的示例:http://plnkr.co/edit/ODyslivLorjaLM4EqlEF?p=preview
myService.getData 函数在初始化 myController 的地方被调用。所以如果你想通过设置getDataSuccess来改变getData函数的行为,你需要在设置getDataSuccess后初始化myController true/false.
我推荐的是这样的
在appSpec.js
describe('myController', function () {
var ctl, serviceMock, getDataSuccess, scope;
beforeEach(function() {
getDataSuccess = true;
serviceMock = {};
module('app', function ($provide) {
$provide.value('myService', serviceMock);
});
inject(function ($q) {
serviceMock.getData = function () {
var defer = $q.defer();
if (getDataSuccess) {
defer.resolve("theData");
} else {
defer.reject("theData");
}
return defer.promise;
};
});
});
beforeEach(inject(function ($rootScope, $controller, $httpBackend, myService) {
scope = $rootScope.$new();
//
// ctl = $controller('myController', {
// $scope: scope,
// myService: myService,
// });
}));
describe('myController loading data', function () {
it('should set $scope.data if data load succeeds', inject(function($controller, myService){
getDataSuccess = true;
ctl = $controller('myController', {
$scope: scope,
myService: myService,
});
scope.$apply();
expect(scope.data).toEqual("theData");
}));
it('should set $scope.serverError if data load fails', inject(function($controller, myService){
getDataSuccess = false;
ctl = $controller('myController', {
$scope: scope,
myService: myService,
});
scope.$apply();
expect(scope.serverError).toEqual("theData");
}));
});
});
我正在尝试测试依赖于服务调用来获取一些数据的控制器方法。服务方法 returns 一个承诺,如果承诺被解决或拒绝,我想测试控制器的行为。
我想出了这种方法来改变我的模拟服务方法的行为,但它不起作用。当调用模拟的 getData
方法时,getDataSuccess
标志始终为真。这是我目前所拥有的:
控制器:
app.controller('myController', function($scope, myService) {
myService.getData()
.then(function (data) {
$scope.data = data;
},
function (data) {
$scope.serverError = data;
});
});
测试:
describe('myController', function () {
var ctl, serviceMock, getDataSuccess, scope;
beforeEach(function() {
getDataSuccess = true;
serviceMock = {};
module('app', function ($provide) {
$provide.value('myService', serviceMock);
});
inject(function ($q) {
serviceMock.getData = function () {
var defer = $q.defer();
if (getDataSuccess) {
defer.resolve("theData");
} else {
defer.reject("theData");
}
return defer.promise;
};
});
});
beforeEach(inject(function ($rootScope, $controller, $httpBackend, myService) {
scope = $rootScope.$new();
ctl = $controller('myController', {
$scope: scope,
myService: myService,
});
}));
describe('myController loading data', function () {
it('should set $scope.data if data load succeeds', function () {
getDataSuccess = true;
scope.$apply();
expect(scope.data).toEqual("theData");
});
it('should set $scope.serverError if data load fails', function () {
getDataSuccess = false;
scope.$apply();
expect(scope.serverError).toEqual("theData");
});
});
});
显然我在这里遗漏了一些东西。执行顺序不是我所期望的。做这种事情的正确方法是什么?
这是 Plunker 中的示例:http://plnkr.co/edit/ODyslivLorjaLM4EqlEF?p=preview
myService.getData 函数在初始化 myController 的地方被调用。所以如果你想通过设置getDataSuccess来改变getData函数的行为,你需要在设置getDataSuccess后初始化myController true/false.
我推荐的是这样的
在appSpec.js
describe('myController', function () {
var ctl, serviceMock, getDataSuccess, scope;
beforeEach(function() {
getDataSuccess = true;
serviceMock = {};
module('app', function ($provide) {
$provide.value('myService', serviceMock);
});
inject(function ($q) {
serviceMock.getData = function () {
var defer = $q.defer();
if (getDataSuccess) {
defer.resolve("theData");
} else {
defer.reject("theData");
}
return defer.promise;
};
});
});
beforeEach(inject(function ($rootScope, $controller, $httpBackend, myService) {
scope = $rootScope.$new();
//
// ctl = $controller('myController', {
// $scope: scope,
// myService: myService,
// });
}));
describe('myController loading data', function () {
it('should set $scope.data if data load succeeds', inject(function($controller, myService){
getDataSuccess = true;
ctl = $controller('myController', {
$scope: scope,
myService: myService,
});
scope.$apply();
expect(scope.data).toEqual("theData");
}));
it('should set $scope.serverError if data load fails', inject(function($controller, myService){
getDataSuccess = false;
ctl = $controller('myController', {
$scope: scope,
myService: myService,
});
scope.$apply();
expect(scope.serverError).toEqual("theData");
}));
});
});