48

一部のディレクティブでは、ディレクティブに固有のロジックを処理する関数をスコープに追加しています。例えば:

link: function(scope, element, attrs) {
         scope.doStuff = function() {
            //do a bunch of stuff I want to test
         }        
      }

その機能をテストするにはどうすればよいですか?ディレクティブをテストする方法をグーグルで調べましたが、見つけたのは要素の変更をテストすることでした。各テストの前にディレクティブをコンパイルすることは確かにできますが、それでは毎回スコープが消去されます。スコープの変更時にプロパティとして関数をテストしたいと思います。

ディレクティブ定義から返されるオブジェクトを取得する方法はありますか?次に、リンク関数を直接呼び出して、スコープで定義された各関数の動作をテストできます。これをすべて行うためのより良い方法はありますか?

Jasmineを使用してテストを実行していますが、関数でスコープを設定したいので、同じスコープデータに対してdescribe複数の関数を使用できます。it

4

5 に答える 5

46

基本的に、リンク関数自体をテストするのではなく、プログラムでディレクティブの結果をテストします。あなたがすることは、文字列にディレクティブを書き、$compileそれを角度処理するために使用することです。次に、出力をテストして、すべてが正しく配線されていることを確認します。

Angularのソースには、これを行う方法の良い例がたくさんあります...たとえば、AngularによるngRepeatディレクティブのテスト

彼らが行っているのは、ディレクティブの設定、スコープの変更(この場合$rootScope)が$digestedであることを確認してから、出力されるDOMをテストして、すべてが正しく接続されていることを確認することです。ディレクティブがスコープを変更している場合は、スコープ内の内容をテストすることもできます。

ngClickのテストも非常に興味深いものです。これは、ブラウザーの相互作用のテストと、スコープへの影響を示しているためです。

完全を期すために、これはngClickテストの抜粋であり、ディレクティブのテストをかなりうまくまとめていると思います。

 it('should get called on a click', inject(function($rootScope, $compile) {
   element = $compile('<div ng-click="clicked = true"></div>')($rootScope);
   $rootScope.$digest();
   expect($rootScope.clicked).toBeFalsy();

   browserTrigger(element, 'click');
   expect($rootScope.clicked).toEqual(true);
 }));

したがって、scope.doStuff関数の場合、スコープに影響を与えるものは何でもテストし、その後DOM要素に影響を与えるのと同じように、関数が何をしているのかをテストしません。

于 2012-11-16T15:59:56.427 に答える
2

必要に応じて、ディレクティブのリンクメソッドを直接単体テストすることができます。angle-iceモジュールのユニットテスターを参照してください:「ディレクティブ構成のテスト」

http://bverbist.github.io/angular-ice/#/unitTester

使用例:https ://github.com/bverbist/angular-ice/blob/master/app/components/icebank/bank-account-number-directive_link_test.js

あなたの場合、ディレクティブのlinkメソッドに渡すスコープオブジェクトへの参照を保持してから、そのスコープでdoStuff関数を直接テストできます。

于 2015-08-03T21:59:39.810 に答える
1

私はこの問題を少し違った方法で解決しました。

ディレクティブに非常に単純なリンク関数があり、3番目の引数( attrs )が必要ない場合は、リンク関数を削除して、代わりにディレクティブにコントローラーを割り当てます。

app.directive('loadIndicator', function() {
  return {
    restrict: 'E',
    replace: true,
    templateUrl: 'blahblah/indicator.html',
    controller: 'LoadIndicatorController'
  };
});

ディレクティブのリンク関数にスコープと要素の引数があるのと同じように、これらの2つの引数は、 $scope$elementとしてテストしやすいコントローラーに挿入できます。

コントローラーを作成し、それらのコントローラーを単体テストできる場合、これは非常に簡単です。

于 2014-10-28T23:44:36.617 に答える
0

@sqlexceptionへのコメント返信で述べられているように。ディレクティブのスコープを実際に把握する必要がありますが、これは難しいことではありません。あなたがしたくないことは、あなたのテストを満たすためにあなたのコードを修正することです、それは逆であるはずです。

ディレクティブのスコープを取得するには、次のようにコンパイルします。

var element = $compile(<directive's html>).($scope)

ここで、$scopeはで宣言され$scope = $rootScrope.$new()ます。これで、次のようにして分離スコープを取得できます。element.scope()

私は最近、これについての短いブログ投稿をここで見つけました。プランカーを使用したリンク関数 のテストを支援します。

于 2015-02-05T18:02:47.623 に答える
0
 it('should get called on a click', inject(function($rootScope, $compile) {
   var scope = $rootScope.$new();
   element = $compile('<div ng-click="doIt()"></div>')(scope);
   scope.$digest();
   expect(scope.$$childHead.doIt()).toBeDefined();
 }));

この$$childHeadを使用することで、同じ問題を解決できました。これにより、テストで呼び出されなかった関数をカバーできます。

于 2018-10-12T17:05:51.110 に答える