Javascript 如何模拟在控制器初始化时运行的函数?
控制器:Javascript 如何模拟在控制器初始化时运行的函数?,javascript,angularjs,unit-testing,karma-runner,Javascript,Angularjs,Unit Testing,Karma Runner,控制器: function myCtrl($scope) { $scope.firstFn = function() { console.log('firstFn called'); $scope.test1 = 2; }; $scope.secondFn = function() { console.log('secondFn called'); $scope.test2 = 3; };
function myCtrl($scope) {
$scope.firstFn = function() {
console.log('firstFn called');
$scope.test1 = 2;
};
$scope.secondFn = function() {
console.log('secondFn called');
$scope.test2 = 3;
};
(function constructor() {
console.log('Controller init.');
$scope.test1 = 1;
$scope.test2 = 2;
$scope.firstFn();
})();
};
是否可以在不执行“firstFn”的情况下为名为“secondFn”的函数编写单元测试?
有可能嘲笑它吗
scope = $rootScope.$new();
ctrl = $controller('myCtrl', {$scope: scope});
// Mock firstFn ?
scope.secondFn();
// assert $scope.test1 = 1
// assert $scope.test2 = 3
只需监视
firstFn
。默认情况下,对spied on函数的任何调用都将是对Jasmine spy对象的调用,而不是对实际函数的调用
scope = $rootScope.$new();
ctrl = $controller('myCtrl', {$scope: scope});
spyOn(scope, 'firstFn');
scope.secondFn();
// assert $scope.test1 = 1
// assert $scope.test2 = 3
有关对间谍行为的更多控制,请参见你需要:
$scope
上创建模拟版本的firstFn
createSpy
和ECMAScript 5方法Object.defineProperty()
来实现这一点
请注意,以下示例使用的是Jasmine 2.0
创建模拟:
firstFnMock = jasmine.createSpy('firstFn').and.callFake(function() {
console.log('firstFnMock called');
});
使用defineProperty
在名为firstFn
的$scope
上创建属性,并将其值设置为模拟函数:
Object.defineProperty($scope, "firstFn", {
enumerable: false,
configurable: false,
writable: false,
value: firstFnMock
});
将writable
设置为false
非常重要,因为这将阻止控制器更换模拟
在正常情况下创建控制器时,使用准备好的$scope
(在本例中设置创建控制器的函数):
规范示例:
it('Spec', function() {
createController();
expect(firstFnMock).toHaveBeenCalled();
$scope.secondFn();
expect($scope.test1).toBe(1);
expect($scope.test2).toBe(3);
});
演示:你在使用任何测试框架吗,也许是Jasmine?是的,我在使用Jasmine。这不起作用,因为函数是在控制器创建后立即执行的。如果函数是控制器专用的,并且它在控制器创建后立即执行,那么你就倒霉了。将其抽象为服务,然后在创建控制器之前对其进行监视。哇,谢谢!我失去了希望。它工作完美无瑕。正是我所需要的:)
it('Spec', function() {
createController();
expect(firstFnMock).toHaveBeenCalled();
$scope.secondFn();
expect($scope.test1).toBe(1);
expect($scope.test2).toBe(3);
});