2017-02-12 9 views
3

私はAngularJS 1.x指令のユニットテストを書いています。
"テンプレート"を使用すると動作します。
"templateUrl"を使用しても機能しません(ディレクティブ要素は、 "compiled"ではなく指定されたHTMLのままで、テンプレートで定義されたHTMLを使用します)。

これは私がジャスミンにテストするためのディレクティブの要素を作成する方法である:

function createDirectiveElement() { 
    scope = $rootScope.$new(); 
    var elementHtml = '<my-directive>my directive</my-directive>'; 
    var element = $compile(elementHtml)(scope); 
    scope.$digest(); 
    if (element[0].tagName == "my-directive".toUpperCase()) throw Error("Directive is not compiled"); 

    return element; 
}; 

(これは実際には実際のコードの更新を参照して、動作しません)

私は$を使用するthis workaroundを使用していますngMockE2EのhttpBackend(ngMockのものではなく)。ブラウザの開発者の「ネットワーク」タブでは、テンプレートファイルへのリクエストは表示されません。 "Object#にはメソッド 'passThrough'がありません"というエラーを解決したので動作するようです。

私は、テンプレートへの呼び出しが$ httpBackend(テンプレートが実際に適用される前に$ compile exitを意味する)を使用して非同期で行われていることを知っています。

私の質問は 明らかに$ compileは私が期待していることをしていません。このエラーをトラップするにはどうしたらいいですか? templateUrlで間違ったアドレスを使用するとエラーは発生しません。 $ compile(指示文)またはスコープ。$ digest()を呼び出したときに問題が発生したことを確認するにはどうすればよいですか?

おかげで、
アレッサンドロ


[ソリューション]

@Corvusoftによって示唆されるように私は$ exceptionHandlerのを注入し、私はすべてのテストの後にエラーをチェック。最後に
これは私が追加したコードのみです:

afterEach(inject(function ($exceptionHandler) { 
    if ($exceptionHandler.errors.length > 0)    
     throw $exceptionHandler.errors; 
})); 

今、私ははっきりとエラーが(コンソールに代わりにそれらの検索の)ジャスミンのテスト結果で発生した見ることができ、例: エラー:予期しない要求:GET/API /カテゴリ/リスト 期待これ以上の要求、エラー:予期しない要求:

を投げそして、最も重要な期待GET/API /カテゴリ/リスト これ以上の要求、私のテストは、場合には渡しませんいくつかのエラーがあります。


templateUrl作業は、コンパイル/消化の終了を待機する非同期beforeEach(「完了」)およびタイムアウトを使用するために実際に本物のコード[更新が実際の例ケースを示すこと]。
私のディレクティブはいくつかのprividers/servicesを使用しています。テンプレートには他のディレクティブが含まれています。これらのディレクティブはtemplateUrlを使用し、リンク関数()内のいくつかのAPIを呼び出します。私は、この例では、他の誰かに役立ちます願ってい

// workaround to have .passThrough() in $httpBackend 
beforeEach(angular.mock.http.init); // set $httpBackend to use the ngMockE2E to have the .passThrough() 
afterEach(angular.mock.http.reset); // restore the $httpBackend to use ngMock 

beforeEach(inject(function (_$compile_, _$rootScope_, _$http_, $httpBackend, $templateCache, $injector) { 
    $compile = _$compile_; 
    $rootScope = _$rootScope_; 
    $http = _$http_; 

    $httpBackend.whenGET(/\/Scripts of my app\/Angular\/*/).passThrough(); 
    $httpBackend.whenGET(/\/api\/*/).passThrough(); // comment out this to see the errors in Jasmine 
})); 

afterEach(inject(function ($exceptionHandler) { 
    if ($exceptionHandler.errors.length > 0)    
     throw $exceptionHandler.errors; 
})); 

beforeEach(function(done) { 
    createDirectiveElementAsync(function (_element_) { 
     element = _element_; 
     scope = element.isolateScope(); 
     done(); 
    }); 
}); 

function createDirectiveElementAsync(callback) { 
    var scope = $rootScope.$new(); 
    var elementHtml = '<my-directive>directive</my-directive>'; 
    var element = $compile(elementHtml)(scope);   
    scope.$digest(); 

    // I haven't found an "event" to know when the compile/digest end 
    setTimeout(function() { 
     if (element.tagName == "my-directive".toUpperCase()) throw Error("Directive is not compiled"); 
     callback(element);    
    }, 0.05*1000); // HACK: change it accordingly to your system/code 
}; 

it("is compiled", function() { 
    expect(element).toBeDefined(); 
    expect(element.tagName).not.toEqual("my-directive".toUpperCase()); 
}); 

これは、現在の(作業)テストコードです。

答えて

2

$exceptionHandler

Any uncaught exception in AngularJS expressions is delegated to this service. The default implementation simply delegates to $log.error which logs it into the browser console.

In unit tests, if angular-mocks.js is loaded, this service is overridden by mock $exceptionHandler which aids in testing.

angular. 
    module('exceptionOverwrite', []). 
    factory('$exceptionHandler', ['$log', 'logErrorsToBackend', function($log, logErrorsToBackend) { 
    return function myExceptionHandler(exception, cause) { 
     logErrorsToBackend(exception, cause); 
     $log.warn(exception, cause); 
    }; 
    }]);