Angularjs 用jasmine模拟Angular控制器中的服务依赖关系
我一直在尝试开始与karma和jasmine一起使用angular进行单元测试,我一直在绞尽脑汁想如何测试具有依赖性的控制器。我试着用一个茉莉花间谍游戏来模仿一个间谍,并把它注册到beforeach钩子里,但由于某种原因,这个间谍没有被认出 代码如下:Angularjs 用jasmine模拟Angular控制器中的服务依赖关系,angularjs,unit-testing,jasmine,Angularjs,Unit Testing,Jasmine,我一直在尝试开始与karma和jasmine一起使用angular进行单元测试,我一直在绞尽脑汁想如何测试具有依赖性的控制器。我试着用一个茉莉花间谍游戏来模仿一个间谍,并把它注册到beforeach钩子里,但由于某种原因,这个间谍没有被认出 代码如下: angular.module('testModule', []) .controller('TestController', [ '$scope', 'TestService', function ($scope, Tes
angular.module('testModule', [])
.controller('TestController', [
'$scope',
'TestService',
function ($scope, TestService) {
$scope.data = TestService.load();
}])
.factory('TestService', function () {
return {
load: function(){
return "foo";
}
}
});
这是测试
describe('TestController', function() {
var $controller, $scope, TestService;
beforeEach(module('testModule'), function($provide){
TestService = jasmine.createSpyObj("TestService", ["load"]);
TestService.load.andReturn("bar");
$provide.value("TestService", TestService)
});
beforeEach(inject(function(_$controller_, $rootScope, _TestService_) {
$scope = $rootScope.$new();
TestService = _TestService_;
$controller = _$controller_('TestController', {
$scope: $scope,
TestService: TestService
});
}));
it('should set $scope.data to bar when TestService.load is called', function() {
expect(TestService.load).toHaveBeenCalled();
expect($scope.data).toEqual("bar");
}); });
测试中的两个断言都失败
当我调用expect(TestService.load).tohavebeencall()时,我得到了“Error:Expected是间谍,但得到了函数”
如果我调用expect($scope.data).toEqual(“bar”),我会得到预期的'foo'等于'bar'。“Foo”来自实际的服务,而不是间谍对象
谢谢你的帮助 在您的
beforeach
中,您正在注入\u TestService\u
,然后通过以下方式覆盖您在前面的beforeach
中声明的内容:
TestService = _TestService_;
删除该代码,测试就会成功
此外,无需这样做:
$provide.value("TestService", TestService)
基本上,当您手动注入不必要的东西时,您尝试使用Angular的依赖注入。而不是
jasmine.createSpyObj
,使用$injector
提供的现有服务,然后模拟单个方法会更容易。您可以使用spyOn
来实现这一点:
describe('TestController', function() {
var $controller, $scope, TestService;
beforeEach(module('testModule'));
beforeEach(inject(function(_$controller_, $rootScope, _TestService_) {
$scope = $rootScope.$new();
TestService = _TestService_;
spyOn(TestService, 'load').and.returnValue('bar');
$controller = _$controller_('TestController', {
$scope: $scope,
TestService: TestService
});
}));
it('should set $scope.data to bar when TestService.load is called', function() {
expect(TestService.load).toHaveBeenCalled();
expect($scope.data).toEqual("bar");
});
});
非常感谢布罗科的回复。我按照你的建议删除了两行,但测试仍然失败。它告诉我:“无法读取未定义的属性‘load’”。看起来它试图调用TestService spyObj上的load,但仍然找不到spyObj。这似乎是我的建议和Davin在回答(你接受了)中向你展示的间谍问题的结合。谢谢Davin。我用上面的代码替换了我的测试,它在调用spyOn的行中返回'cannotreadproperty'returnValue'of undefined'。我把它改为:spyOn(TestService,'load')。andReturn('bar'),现在测试是绿色的。“and.return.”是Jasmine 2.0语法,对吗?那么一定是Jasmine 2.0。如果
andReturn
有效,那就太好了!