1

controllerAs 構文を使用するコントローラーをテストしようとしています。私の問題は、コントローラーで関数をテストしようとすると、「未定義であると予想されます」というメッセージが表示されることです。

コントローラー(短縮版)

(function (angular) {
  'use strict';

  /* @ngInject */
  function PreflightCtrl($state, $window, $timeout, $stateParams, toastr, accountService, servicesService, geoService, visitService, localStorageService, Notifications, service, UTILS) {

    /* Exported Vars */
    var vm = this;

    /* Exported functions */
    vm.verifyDob = verifyDob;

    function verifyDob() {
      if (!vm.form.dob || (vm.form.dob.length !== 8 && vm.form.dob.length !== 10)){
        return;
      }
      if(vm.form.dob.length === 8){
        var lastTwoDigits = vm.form.dob.substr(vm.form.dob.length-2);
        if(lastTwoDigits === '19'){
          return;
        }
      }
      var dob = new Date(vm.form.dob);
      vm.verifyingDob = true;
      accountService.verifyDOB(dob)
        .success(function(data){
          vm.genderDisabled = false;
          vm.dobError = false;
          $timeout(function() {
            dobInput.blur();
          });
        })
        .error(function (status) {
          vm.genderDisabled = true;
          vm.dobError = true;
        })
        .finally(function () {
          vm.verifyingDob = false;
        });
    }
  }

  angular
    .module('app')
    .controller('PreflightCtrl', PreflightCtrl);

}(angular));

テスト

describe('PreflightCtrl', function(){
  var PreflightCtrl, $state, $window, $timeout, $stateParams, toastr, accountService, servicesService, geoService, visitService, localStorageService, Notifications, service, UTILS, mockAccountService, mockServicesService;

  beforeEach(module('app'));

  beforeEach(inject(function($controller, _$state_, _$window_, _$timeout_, _$stateParams_, _toastr_, _accountService_, _servicesService_, _geoService_, _visitService_, _localStorageService_, _Notifications_, _UTILS_){

    //mock services used in PreflightCtrl
    mockAccountService = {
      verifyDOB: function verifyDOB(dob){
        return {
          success: function(callback){
            callback(dob);
          }
        }
      },
      isPermUser: function isPermUser(){
        return {
          success: function(callback){
            callback(true);
          }
        }
      },
      profile: {
        gender: 'male'
      }
    };

    mockServicesService = {
      isGenderAllowed: function isGenderAllowed(serviceCode, gender){
        return true;
      }
    }

    //prepare for dependency injection
    $state = _$state_;
    $window = _$window_;
    $timeout = _$timeout_;
    $stateParams = _$stateParams_;
    toastr = _toastr_;
    accountService = mockAccountService;
    servicesService = mockServicesService;
    geoService = _geoService_;
    visitService = _visitService_;
    localStorageService = _localStorageService_;
    Notifications = _Notifications_;
    service = {"id": 3, "code": "HL", "flags": {"multi_medicine": false}, "genders": ["male"], "name": "Hair Loss", "product": {"count": 3}, "visible": 1};
    UTILS = _UTILS_;

    //spy on the mocked services
    spyOn(accountService, 'verifyDOB').and.callThrough();
    spyOn(servicesService, 'isGenderAllowed').and.callThrough();

    //create the controller
    PreflightCtrl = $controller('PreflightCtrl', {
      $state: $state,
      $window: $window,
      $timeout: $timeout,
      $stateParams: $stateParams,
      toastr: toastr,
      accountService: accountService,
      servicesService: servicesService,
      geoService: geoService,
      visitService: visitService,
      localStorageService: localStorageService,
      Notifications: Notifications,
      service: service,
      UTILS: UTILS
    });

  }));

  it('should have a defined controller', function(){
    expect(PreflightCtrl).toBeDefined();
  });

  it('should have a defined function called verifyDob', function(){
    console.log(PreflightCtrl);
    expect(PreflightCtrl.verifyDob).toBeDefined();
  });

  it('should verify a DOB', function(){

    PreflightCtrl.form.dob = '01/01/1990';
    PreflightCtrl.verifyDob();
    expect(PreflightCtrl.verifyingDob).toBe(false);
  });
});

テストを実行すると、次の出力が得られます。

「カルマ:ユニット」(カルマ) タスクの実行 PhantomJS 1.9.8 (Mac OS X 0.0.0) ログ:「警告: angular を複数回ロードしようとしました。」

ログ: Promise{$$state: Object{status: 2, value: Error{message: ...}}} PhantomJS 1.9.8 (Mac OS X 0.0.0) PreflightCtrl には、verifyDob という関数が定義されている必要があります。定義されます。/Users/tracy/Projects/LemonaidClinic/src/views/preflight/preflight.controller.spec.js:80 で、PhantomJS 1.9.8 (Mac OS X 0.0.0) PreflightCtrl は DOB FAILED TypeError を検証する必要があります: 'undefined' はありません/Users/tracy/Projects/LemonaidClinic/src/views/preflight/preflight.controller.spec.js:85 PhantomJS 1.9.8 ( Mac OS X 0.0.0): 15 のうち 15 を実行 (2 失敗) (0.006 秒 / 0.204 秒) 警告: タスク "karma:unit" が失敗しました。--force を使用して続行します。

警告のため中止されました。

行 80 は次の行です。

85 行目は次のとおりです。 PreflightCtrl.form.dob = '01/01/1990';

最初の行がコントローラーのログであることがわかります。これは、必要な関数や変数がコントローラーにないことを意味する promise を返します。

Angular が複数回ロードしようとしている理由もわかりませんが、他のテストには影響していないようです。

私は何を間違っていますか?

前もって感謝します。

4

1 に答える 1

0

私はもっ​​とこのようにします:

var スコープ = $rootScope.$new();

$controller('myController as vm', {$scope:scope, /*あなたの依存ツリー地獄*/});
$rootScope.$apply();

vm = scope.vm;// これは新しいコントローラです。テストで参照できます。

あまりにも多くのモックを作成する必要があるという事実は、コントローラーの依存関係が直接的および/または間接的に多すぎることを示していると思います。

ただし、それを修正する立場にない場合は、「モック」というフォルダーを作成し、実際のファイルと同じ ID を持つファイルをドロップして、カルマにそのフォルダーをポイントさせるだけで、より簡単にモックできます。これらは実際の依存関係を上書きします。欠点は、登録済みのモックとは異なるものが必要な場合は、1 回限りのモックを作成する必要があることですが、テストごとにモックを設定する必要がなくなります。

于 2015-12-21T19:23:24.847 に答える