controllerAs仕様のcontrollerをユニットテストするための小ネタ

小ネタです。
いつもangularのcontrollerを使うときはui-routerからcontrollerAsして使うことが多いですが、
controllerAs仕様にしたcontrollerをユニットテストする際、少しハマったのでそのあたりを紹介します。

テストコードはangular本家のPhoneCatチュートリアルのものを利用します。

controllerAs仕様にカスタムしたcontroller

contorller.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(function() {
'use strict';

angular.module('phonecatApp').controller('PhoneListCtrl', PhoneListCtrl);

function PhoneListCtrl() {

var vm = this;
vm.phones = [{
'name': 'Nexus S',
'snippet': 'Fast just got faster with Nexus S.',
'age': 1
}, {
'name': 'Motorola XOOM™ with Wi-Fi',
'snippet': 'The Next, Next Generation tablet.',
'age': 3
}, {
'name': 'MOTOROLA XOOM™',
'snippet': 'The Next, Next Generation tablet.',
'age': 2
}];

}

})();

こちらがテストコード。

controllersSpec.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
'use strict';

describe('Controller: PhoneListCtrl', function () {

// load the controller's module
beforeEach(module('phonecatApp'));

var MainCtrl,
scope;

// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {

MainCtrl = $controller('PhoneListCtrl as vm', {
$scope: scope
});

}));

it('phoneモデルが3つ作成されていること', function () {
expect(scope.vm.phones.length).toBe(3);
});

});

$controllerで指定するcontrollerのconstructor指定の部分にas構文が使えるんですね。知りませんでした。
$controllerでテストするcontrollerをinjectしたら、scopeに設定したmodelなどはasで指定したalias(今回だとvm)から参照できるみたい。

ちなみに、constructorでas構文を使わないとexpectするところでundefinedになります。

1
TypeError: 'undefined' is not an object (evaluating 'scope.phones.length')