2015-01-13

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

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

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

controllerAs仕様にカスタムしたcontroller

contorller.js

(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

'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になります。

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