Angular中的单元测试很新。我已经读过关于间谍,存根和嘲笑的负载,但是我在执行基础知识方面遇到了很多麻烦:
initializePage
?Controller.spec(非常确定需要以下内容)
'use strict';
describe('Controller: MainController', function() {
// load the controller's module
beforeEach(module('myApp'));
var MainController, scope;
// Initialize the controller and a mock scope
beforeEach(inject(function($controller, $rootScope) {
scope = $rootScope.$new();
MainController = $controller('MainController', { $scope: scope });
}));
其余规格:
it('should have called initializePage', function() {
var spyInstance = sinon.spy(MainController, "initializePage");
assert(spyInstance.called, "initializePage() was not called once");
});
});
我一直认为间谍就足够了,但我不确定MainController
是否被执行。目前spyInstance
抛出错误。 我需要这里的存根吗?为什么?
控制器
class MainController {
constructor($scope, $http, $state, Session) {
this.$scope = $scope;
this.$state = $state;
this.Session = Session;
this.initializePage();
}
initializePage() {
//blah blah
}
感谢。
<小时/> 的修订: main.controller.spec.js
describe('Controller: MainController', function() {
// load the controller's module
beforeEach(module('scriybApp'));
var mainControllerInstance, scope;
// Initialize the controller and a mock scope
beforeEach(inject(function($controller, $rootScope) {
scope = $rootScope.$new();
mainControllerInstance = $controller('MainController', { $scope: scope });
}));
it('should test the controller is in order', function() {
assert.isFunction(mainControllerInstance.$onInit, "$onInit() has not been defined");
sinon.spy(mainControllerInstance, "$onInit");
assert(mainControllerInstance.$onInit.called, "$onInit() called = false");
});
});
答案 0 :(得分:1)
控制器测试在Angular中存在一些缺陷。主要是因为不可能监视只作为类实例($controller(...)
的结果是)的类的构造函数。调用$controller(...)
时,没有什么可以窥探的,构造函数已被调用,故事结束。
为此目的,除了Angular模块之外,还应该使用ES6 / CommonJS模块来公开控制器类和间谍原型方法。由于ES6已经在项目中使用,因此
export class MainController { ... }
和
import { MainController } from '...';
...
scope = $rootScope.$new();
sinon.spy(MainController.prototype, 'initializePage');
mainControllerInstance = $controller('MainController', { $scope: scope });
assert(MainController.prototype.initializePage.called);
assert.strictEqual(mainControllerInstance.$scope, $scope);
...
但更重要的是,initializePage
重新发明轮子。它的工作已由Angular 1.5及更高版本中的$onInit
生命周期钩子处理。它在指令编译时自动调用,可以作为预链接函数的替代。
$onInit
在控制器实例化时没有被调用,但是可以安全地假设它将处于指令中,因此不需要将间谍放在它上面。它更适合测试,测试成为
class MainController {
constructor($scope, $http, $state, Session) {
this.$scope = $scope;
this.$state = $state;
this.Session = Session;
}
$onInit() {
//blah blah
}
}
和
scope = $rootScope.$new();
mainControllerInstance = $controller('MainController', { $scope: scope });
assert.isFunction(mainControllerInstance.$onInit);
assert.strictEqual(mainControllerInstance.$scope, $scope);
...