一部のディレクティブでは、スコープに関数を追加して、ディレクティブに固有のロジックを処理しています。例えば:
link: function(scope, element, attrs) {
scope.doStuff = function() {
//do a bunch of stuff I want to test
}
}
その機能をテストするにはどうすればよいですか?私はディレクティブをテストする方法をグーグルで探しましたが、 私が見つけたもの は要素の変更をテストすることに関するものでした。確かに、各テストの前にディレクティブをコンパイルできますが、それは毎回スコープを一掃します。スコープ変更のプロパティとして関数をテストしたい。
ディレクティブ定義から返されるオブジェクトを保持する方法はありますか?次に、リンク関数を直接呼び出して、スコープで定義された各関数の動作をテストできます。これをすべて行うより良い方法はありますか?
Jasmineを使用してテストを実行していますが、describe
関数でスコープをセットアップしたいので、同じスコープデータに対して複数のit
関数を使用できます。
基本的に、リンク関数自体をテストするのではなく、プログラムでディレクティブの結果をテストします。ディレクティブを文字列に書き出し、$compile
を使用してangularで処理します。出力をテストして、すべてが正しく接続されていることを確認します。
Angularのソースには、これを行う方法の良い例がたくさんあります。たとえば、 AngularによるngRepeatディレクティブのテスト
ディレクティブの設定、スコープの変更(この場合は$rootScope
)が$digest
edであることを確認し、出力される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
関数の場合、私はそれが何であるかをテストするのと同じように、それが何であるかをテストしませんdoingスコープで、その後DOM要素に影響します。
必要に応じて、ディレクティブのリンクメソッドを直接単体テストすることができます。角氷モジュールのユニットテスターを参照してください:「ディレクティブ構成のテスト」
http://bverbist.github.io/angular-ice/#/unitTester
あなたの場合、ディレクティブのリンクメソッドに渡すスコープオブジェクトへの参照を保持し、そのスコープでdoStuff関数を直接テストできます。
私はこの問題を少し異なって解決しました。
ディレクティブに非常に単純なリンク関数があり、3番目の引数(attrs)が必要ない場合は、リンク関数を削除してディレクティブにcontroller代わりに。
app.directive('loadIndicator', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'blahblah/indicator.html',
controller: 'LoadIndicatorController'
};
});
ディレクティブのリンク関数にスコープと要素の引数があるように、これら2つの引数は$ scopeおよび$ elementとしてテストしやすいコントローラーに挿入できます。 。
コントローラーを作成し、それらのコントローラーを単体テストできる場合、これは非常に簡単です。
@sqlexceptionへのコメント返信で述べられているように。本当にディレクティブのスコープのハンドルを取得する必要がありますが、これは難しくありません。あなたがしたくないことは、テストを満足させるためにコードを修正することです。
ディレクティブのスコープを取得するには、次のようにコンパイルします。
var element = $compile(<directive's html>).($scope)
ここで_$scope
_は$scope = $rootScrope.$new()
で宣言されています。 element.scope()
を実行することで分離スコープを取得できます
私は最近、これについて短いブログ投稿を書きました リンク関数のテスト
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を使用することは、同じ問題の解決策でした。これにより、テストで呼び出されなかった関数をカバーできます。