Angular1.5+ 的component語法很贊, 但是對它們做單元測試時難住了我.
指令的測試向來比較繁瑣, 需要$compile拿到element, 在通過element得到controller.
beforeEach(angular.mock.inject($injector => {
$compile = $injector.get('$compile');
$rootScope = $injector.get('$rootScope');
scope = $rootScope.$new();
element = $compile(`
<input name="tel" ng-model="tel" type="tel"/>
`)(scope);
$rootScope.$apply();
controller = element.controller('ngModel');
}));
雖然component是directive的語法糖, 但是它的測試卻有點不太一樣, 在component doc 中提到了一個$componentController服務(wù), 它包含在ngMock中, 這個服務(wù)的優(yōu)點在于你可以不用創(chuàng)建DOM元素就能測試controller.
Component測試實例
假設(shè)有如下Component
export const FormRenderComponent = {
template,
controller,
bindings: {
data: '<',
name: '@',
onSave: '&'
}
};
---Magic Is Here---
為了拿到該組件的控制器, 代碼非常簡單.
let $componentController, controller;
let bindings = {
data: [],
name: 'form name',
onSave: angular.noop
};
beforeEach(angular.mock.inject($injector => {
$componentController = $injector.get('$componentController');
controller = $componentController('formRender', null, bindings);
}));
$componentController的第一個參數(shù)就是需要測試的組件名, 通過.component注冊在模塊上的, 第二個參數(shù)是locals可以用來提供$scope, $attr, $element, 第三個參數(shù)是bindings的值. 如需更詳細(xì)的描述請查閱官方文檔. 如果你locals幾個對象全用上了, 變得很復(fù)雜, 建議還是用$compile的方式拿controller.
.component('formRender', FormRenderComponent)
測試代碼就就隨意發(fā)揮了, 舉個簡單的例子, 測試bindings的數(shù)據(jù)是否賦值成功.
it('bindings should work', () => {
expect(controller.data).toEqual(bindings.data);
expect(controller.name).toEqual(bindings.name);
});
不要忘了$onInit()
如果你的組件實現(xiàn)了$onInit生命周期函數(shù), 進(jìn)行測試的時候必須確保手動調(diào)用, $ 否則不會觸發(fā).
it('$onInit() should init data and events', () => {
spyOn(controller, 'initData');
spyOn(controller, 'initEvents');
controller.$onInit();
expect(controller.initData).toHaveBeenCalled();
expect(controller.initEvents).toHaveBeenCalled();
});
為了代碼的質(zhì)量和可讀性, 單元測試是必須的, 如果你還沒有養(yǎng)成寫單元測試的習(xí)慣, 那就從現(xiàn)在開始吧.