2016-09-20 6 views
0

私はテストしようとしているキーボードショートカット指令を持っています。イベントデータで$rootScope.$broadcast()をトリガーするのが目的です。アプリケーションでは何の問題もなく動作しますが、私は徹底的に私が望むようにこのダン・テストを通過することはできません。ユニットテストのために

(function(){ 
    'use strict'; 

    angular 
     .module('app.common') 
     .directive('keyboardShortcuts', keyboardShortcuts); 

    // @ngInject 
    function keyboardShortcuts($document, $rootScope){ 
     return { 
      restrict: 'A', 
      link 
     } 

     function link(scope, el, attrs){ 
      $document.bind('keypress', event => { 
       console.log('detected keypress'); 
       $rootScope.$broadcast('keyboardShortcut', event); 

       scope.$digest(); // seems to make no difference 
      }); 
     } 
    } 

})(); 

、私は放送が実際に作られたとに耳を傾けていることを示すために$scope.$onハンドラを追加しましたが、何らかの理由でスパイはそれが仕事ですやっていません。

describe('KeyboardShortcuts Directive', function(){ 
    'use strict'; 

    let $element; 
    let $scope; 
    let vm; 
    let $document; 
    let $rootScope; 

    const mockKeyboardEvent = { 
     type: 'keypress', 
     bubbles: true, 
     altKey: false, 
     ctrlKey: false, 
     shiftKey: false, 
     which: 106 
    } 

    beforeEach(module('app.common')); 

    beforeEach(inject(function(_$rootScope_, $compile, _$document_){ 
     $element = angular.element('<div keyboard-shortcuts></div>'); 
     $rootScope = _$rootScope_.$new(); 
     $document = _$document_; 

     $scope = $rootScope.$new(); 
     $compile($element)($scope); 
     $scope.$digest(); 

     spyOn($rootScope, '$broadcast'); 
    })); 

    //////////// 

    it('should broadcast when a key is pressed', function(){ 
     $scope.$on('keyboardShortcut', (event, data) => { 
      console.log('wtf!?'); 
      expect(data.which).toBe(106); 
     }); 

     $document.triggerHandler(mockKeyboardEvent); 

     $scope.$digest(); // seems to make no difference 

     expect($rootScope.$broadcast).toHaveBeenCalled(); 
    }); 
}); 

コンソールの出力は次のとおりです。そうでなければコードが動作しているように見えます。

[15:33:57] Starting 'build:common:js'... 
[15:33:58] Finished 'build:common:js' after 227 ms 
[15:33:58] Starting 'test:common'... 
20 09 2016 15:33:58.250:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/ 
20 09 2016 15:33:58.250:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency 
20 09 2016 15:33:58.253:INFO [launcher]: Starting browser PhantomJS 
20 09 2016 15:33:58.797:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#37Fv2zndO5Z6XAZ8AAAg with id 3035140 
.. 
LOG: 'detected keypress' 
LOG: 'wtf!?' 
PhantomJS 2.1.1 (Mac OS X 0.0.0) KeyboardShortcuts Directive should broadcast when a key is pressed FAILED 
    Expected spy $broadcast to have been called. 

これまで、ユニットテストコントローラの場合、このようなトラブルもありました。私は即時に実行されたactivate()メソッドで実行されたメソッドを偵察しようとしていましたが、コントローラがインスタンス化されたの上にspyOn(...)メソッドを置くことでスパイを動作させることができました。この場合、私はspyOnを 'beforeEach'の中のあらゆる場所に置こうとしましたが、何も違いは見えませんでした。

私も$onハンドラの内部でexpect..broadcast..beenCalled()ものを置くことの明白な解決策を試してみましたが、それはその主張が通ると放送が行われたことを証明合計であっても、いずれかの動作しませんでした。

私は、$ rootScopeがスパイされているのと同じように$ rootScopeが注入され、別の方法で動作していると感じていると思いますが、どうすればいいのか分かりません。

答えて

0

適切な変数命名が重要です。

この

$rootScope = _$rootScope_.$new(); 

は、角度ユニットテストにおける広範なミスの一つです。

$rootScopeと呼ばれるものは、ルートスコープではなく、子スコープにすぎないという問題があります。それが表示されたとして、この、いくつかの範囲でそう

spyOn($rootScope, '$broadcast'); 

スタブ$broadcast方法を忘れがちです。

それはjQueryの/ jqLit​​eイベントがサイクルを消化するために結ばれていないので、あってはならない

$rootScope = _$rootScope_; 
    $scope = $rootScope.$new(); 

そして

$scope.$digest(); // seems to make no difference 

でなければなりません。

+0

'$ rootScope = _ $ rootScope_.new()'を変更すると、そのトリックが完了したようです。私はそのようにしないで別のテストでいくつかの問題を抱えていたので、私はパターンを保ったのです。私はこれらのテストをもう一度チェックしなければならないようだ。ありがとうございました! – coblr

+0

もちろん、よろしくお願いします。 – estus

関連する問題