我有一个类似的AngularJS控制器:
app.controller('MyCtrl', function($scope, myFactory){
$scope.types = myFactory.getTypes();
$scope.model= {};
$scope.model.type = $scope.types[0].type;
});
});
一切正常。
但我想在Jasmine中测试这个控制器。
所以我嘲笑myFactory
并初始化myCtrl
:
describe('Controllers: MyCtrl', function () {
var MyCtrl, mockedFactory, scope;
beforeEach(module('app.factories', function ($provide) {
mockedFactory = {
getTypes: function(){}
};
spyOn(mockedFactory, 'getTypes');
$provide.value('myFactory', mockedFactory);
}));
beforeEach(module('app'));
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
MyCtrl= $controller('MyCtrl', {
$scope: scope
});
}));
it('should call AccordTypeFactory.getAvailableTypes()', function () {
scope.types;
expect(mockedFactory.getTypes).toHaveBeenCalled();
});
但我有一个逻辑错误:Cannot read property 0 of undefined
我理解这个错误;因为我嘲笑工厂我的控制器属性$scope.model.type
它是未定义的,因为它通过$scope.types
使用工厂的结果。
我的问题很简单:如何让我的考试成功?
Thx guys
答案 0 :(得分:1)
beforeEach(module('app.factories', function ($provide) {
mockedFactory = {
getTypes: function(){ return [{}]; }
};
spyOn(mockedFactory, 'getTypes').andCallThrough();
$provide.value('myFactory', mockedFactory);
}));
如果我理解正确你的问题是模拟器没有返回数组,而你的控制器期望它总是至少有1个元素。您可以设置模拟以返回带有元素的数组,然后在间谍上使用andCallThrough()
让它实际调用模拟。
如果您的工厂可能在应用程序运行时返回空数组,您可能想要在尝试访问types[0]
之前检查数组是否包含至少一个元素
答案 1 :(得分:0)
我发现比我更好的解决方案。
我只需在spyOn之后添加andReturn函数:
spyOn(mockedFactory, 'getTypes').andReturn([{type: 'MockType'}]);