Unit Test - $componentController

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(`
        
    `)(scope);
    $rootScope.$apply();
    controller = element.controller('ngModel');
}));

虽然component是directive的语法糖, 但是它的测试却有点不太一样, 在component doc 中提到了一个$componentController服务, 它包含在ngMock中, 这个服务的优点在于你可以不用创建DOM元素就能测试controller.

Component测试实例

假设有如下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的第一个参数就是需要测试的组件名, 通过.component注册在模块上的, 第二个参数是locals可以用来提供$scope, $attr, $element, 第三个参数是bindings的值. 如需更详细的描述请查阅官方文档. 如果你locals几个对象全用上了, 变得很复杂, 建议还是用$compile的方式拿controller.

.component('formRender', FormRenderComponent)

测试代码就就随意发挥了, 举个简单的例子, 测试bindings的数据是否赋值成功.

it('bindings should work', () => {
    expect(controller.data).toEqual(bindings.data);
    expect(controller.name).toEqual(bindings.name);
});

不要忘了$onInit()

如果你的组件实现了$onInit生命周期函数, 进行测试的时候必须确保手动调用, $ 否则不会触发.

it('$onInit() should init data and events', () => {
    spyOn(controller, 'initData');
    spyOn(controller, 'initEvents');
    controller.$onInit();
    expect(controller.initData).toHaveBeenCalled();
    expect(controller.initEvents).toHaveBeenCalled();
});

为了代码的质量和可读性, 单元测试是必须的, 如果你还没有养成写单元测试的习惯, 那就从现在开始吧.

你可能感兴趣的:(Unit Test - $componentController)