$httpBackend

概要

擬似HTTPバックエンド実装を、$httpサービス を使用するアプリケーションのユニットテストに適用します。

注意: 擬似HTTPバックエンド実装のE2E(エンドツーエンド)テストへの適用、またはバックエンド無しの環境については、 E2Eの$httpBackendモックを参照してください。

ユニットテストでは、素早くユニットテストが行えて外部への依存が無いことが望ましいため、 実際のサーバへのXHRXHR、 またはJSONPのリクエストを送信したくありません。 ここで必要なことは、正しいリクエストが送られたか否か、または代わりにアプリケーションにリクエストを作成させて、 予め用意したレスポンスに応じ、その最終的な結果が期待通りかどうかを検証することです。(翻訳に自信なし)

このモックの実装は、expectとwhenのAPIとそれらの略記(expectGET、whenPOST等)を介して、 静的または動的なレスポンスの応答に使用することが出来ます。

Angularアプリケーションがサーバからのデータを必要とする際は、 実際のサーバにリクエストを送信する$httpBackendサービスを使用した$httpサービスを呼び出します。 依存性注入(DI)であれば、$httpBackendのモック($httpBackendとして同じAPIを持つ)を注入し、 実際のサーバーにリクエストを送ること無く、これを使用してあるテストデータのリクエストとレスポンスの検証を容易に行うことが出来ます。

HTTPリクエストのテストコードを書く際に、バックエンドのモックを使用してHTTPレスポンスとして返るべきテストデータを指定するのには、 2つの方法が存在します。

$httpBackend.expect
期待するリクエストを指定します。
$httpBackend.when
バックエンドの定義を指定します。

期待するリクエスト vs バックエンド定義

"期待するリクエスト"は、リクエストのアサーションを作成する方法と、それらのリクエストのためのレスポンスを定義する方法を提供します。 もし、期待するリクエストが作成されない、または間違った方法で作成された場合は、テストは失敗します。

"バックエンド定義"は、特定のリクエストが行われたり、リクエストが行われた場合に用意されたレスポンスを返した場合に、 アサートしない偽装バックエンドの定義を可能にしてくれます。(翻訳に自信なし) このテストは、テスト中にリクエストが行われたか否かを判定されます。(翻訳に自信なし)

  期待するリクエスト バックエンド定義
文法 .expect(...).respond(...) .when(...).respond(...)
一般的な用途 厳格なユニットテスト 緩い(ブラックボックス)のユニットテスト
複数リクエストの実行 NO YES
リクエストの順番 YES NO
リクエスト必須 YES NO
レスポンス必須 任意(詳細は後述) YES

"バックエンド定義"と"期待するリクエスト"の両方がユニットテスト中に指定された場合、 "期待するリクエスト"が先に評価されます。

もし、"期待するリクエスト"にレスポンスが指定されなかった場合、 AngularJSは、適切なレスポンスのためのバックエンド定義を探します。

もし、リクエストが期待に沿うものでは無かった、またはレスポンスが定義されていなかった場合、 バックエンド定義が、それらのいずれかのリクエストにマッチするか順番に評価され、最初にマッチした定義のレスポンスが返ります。

HTTPリクエストのフラッシュ(flush)

$httpBackendが本環境で使用される場合、常に非同期でリクエストに応答します。 もし、ユニットテストでこの挙動が保持されると、 コーディングやメンテナンスが困難な非同期のユニットテストを作成しなければならなくなります。 テスト対象のコード実行が変更されてしまうため、同時にモックをテストしても、 それを同期して受け取ることが出来ません。(翻訳に自信なし) このため、$httpBackendモックは、保留中のリクエストを明示的ににフラッシュすることで、 同期実行が許可されたテスト中にバックエンドの非同期APIを保持するflush()メソッドを持ちます。(翻訳に自信なし)

$httpBackendモックによるユニットテスト

下記のコードは、コントローラーをユニットテストする際のバックエンドのモックの設定と使用方法になります。 まず、テスト対象となるコントローラーを作成します。

// コントローラーのコード
function MyController($scope, $http) {
  var authToken;

  $http.get('/auth.py').success(function(data, status, headers) {
    authToken = headers('A-Token');
    $scope.user = data;
  });

  $scope.saveMessage = function(message) {
    var headers = { 'Authorization': authToken };
    $scope.status = 'Saving...';

    $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
      $scope.status = '';
    }).error(function() {
      $scope.status = 'ERROR!';
    });
  };
}

では、バックエンドのモックを設定し、Specテストを作成してみましょう。

// コントローラーのテスト
describe('MyController', function() {
   var $httpBackend, $rootScope, createController;

   beforeEach(inject(function($injector) {
     // HTTPサービスレスポンスのモックの設定
     $httpBackend = $injector.get('$httpBackend');
     // 全てのテスト共通のバックエンド定義
     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});

     // スコープを保持(例: ルートスコープ)
     $rootScope = $injector.get('$rootScope');
     // $controllerサービスは、コントローラーのインスタンス作成に使用されます
     var $controller = $injector.get('$controller');

     createController = function() {
       return $controller('MyController', {'$scope' : $rootScope });
     };
   }));


   afterEach(function() {
     $httpBackend.verifyNoOutstandingExpectation();
     $httpBackend.verifyNoOutstandingRequest();
   });


   it('should fetch authentication token', function() {
     $httpBackend.expectGET('/auth.py');
     var controller = createController();
     $httpBackend.flush();
   });


   it('should send msg to server', function() {
     var controller = createController();
     $httpBackend.flush();

     // ここでは認証を気にすることはありませんが、
     // コントローラーはまだリクエストを送信し、
     // $httpBackendは期待するリクエストの指定無しに応答します。(翻訳に自信なし)
     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
     $rootScope.saveMessage('message content');
     expect($rootScope.status).toBe('Saving...');
     $httpBackend.flush();
     expect($rootScope.status).toBe('');
   });


   it('should send auth header', function() {
     var controller = createController();
     $httpBackend.flush();

     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
       // ヘッダーが送られた場合、それが期待したものでない、
       // リクエストに一致しなければ、テストは失敗します。
       return headers['Authorization'] == 'xxx';
     }).respond(201, '');

     $rootScope.saveMessage('whatever');
     $httpBackend.flush();
   });
});

expect(method, url, data, headers)

新しく"期待するリクエスト"を作成します。

引数 説明
method

型:string

HTTPメソッドを指定します。

url

型:stringRegExp

HTTPのURLを指定します。

data(optional)

型:stringRegExpfunction(string)Object

HTTPリクエストのボディ、 または、data文字列受け取り期待したデータであればtrueを返す関数、 または、リクエストのボディがJSONフォーマットのオブジェクトのいずれかを指定します。

headers(optional)

型:Objectfunction(Object)

HTTPヘッダー、またはHTTPヘッダーオブジェクトを受け取り、 もし最新の期待するものであればtrueを返す関数のどちらかを指定します。

戻り値 引数
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

respond – {function([status,] data[, headers]) | function(function(method, url, data, headers)}
返された静的なデータ設定を取得する応答メソッド、またはレスポンスのステータス(数値)、 レスポンスのデータ(文字列)、レスポンスヘッダー(オブジェクト)を含む配列を返すことが出来る関数です。

expectDELETE(url, headers)

DELETE用に、"期待するリクエスト"を新しく作成します。 詳細は、expect()を参照してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

headers(optional)

型:Object

HTTPヘッダーを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

expectGET(url, headers)

GET用に、"期待するリクエスト"を新しく作成します。 詳細は、expect()を参照してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

headers(optional)

型:Object

HTTPヘッダーを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

expectHEAD(url, headers)

HEAD用に、"期待するリクエスト"を新しく作成します。 詳細は、expect()を参照してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

headers(optional)

型:Object

HTTPヘッダーを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

expectJSONP(url)

JSONP用に、"期待するリクエスト"を新しく作成します。 詳細は、expect()を参照してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

expectPATCH(url, data, headers)

PATCH用に、"期待するリクエスト"を新しく作成します。 詳細は、expect()を参照してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

data(optional)

型:stringRegExpfunction(string)Object

HTTPリクエストのボディ、 または、data文字列受け取り期待したデータであればtrueを返す関数、 または、リクエストのボディがJSONフォーマットのオブジェクトのいずれかを指定します。

headers(optional)

型:Object

HTTPヘッダーを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

expectPOST(url, data, headers)

POST用に、"期待するリクエスト"を新しく作成します。 詳細は、expect()を参照してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

data(optional)

型:stringRegExpfunction(string)Object

HTTPリクエストのボディ、 または、data文字列受け取り期待したデータであればtrueを返す関数、 または、リクエストのボディがJSONフォーマットのオブジェクトのいずれかを指定します。

headers(optional)

型:Object

HTTPヘッダーを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

expectPUT(url, data, headers)

PUT用に、"期待するリクエスト"を新しく作成します。 詳細は、expect()を参照してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

data(optional)

型:stringRegExpfunction(string)Object

HTTPリクエストのボディ、 または、data文字列受け取り期待したデータであればtrueを返す関数、 または、リクエストのボディがJSONフォーマットのオブジェクトのいずれかを指定します。

headers(optional)

型:Object

HTTPヘッダーを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

flush(count)

用意されているレスポンスを使用して、保留になっているリクエストをフラッシュします。

引数 説明
count(optional

型:number

フラッシュ(到着した順に)するレスポンスの数値を指定します。 もし未定義であれば、保留中の全てのリクエストがフラッシュされます。 もし、flushメソッドが呼ばれた際に、保留中のリクエストが無ければ、スローされます。 (これは、一般的にはプログラミングエラーのサインです)

resetExpectations()

全ての"期待するリクエスト"をリセットしますが、全ての"バックエンド定義"は維持されます。 一般的に、$httpBackendモックの同じインスタンスを再利用したい際の、 多重(?)テストの段階でresetExpectationsを呼び出すことになるでしょう。(翻訳に自信なし)

verifyNoOutstandingExpectation()

全てのリクエストが、expectのAPI作成を介して定義されているかを検証します。 もし、いずれかのリクエストがそうでない場合、verifyNoOutstandingExpectationは例外をスローします。

一般的にこのメソッドは、"afterEach"を使用したリクエストをアサートする下記のeachテストのようなケースで呼び出されます。

afterEach($httpBackend.verifyNoOutstandingExpectation);

verifyNoOutstandingRequest()

フラッシュする必要のない未処理のリクエストが無いことを検証します。

一般的にこのメソッドは、"afterEach"を使用したリクエストをアサートする下記のeachテストのようなケースで呼び出されます。

afterEach($httpBackend.verifyNoOutstandingRequest);

when(method, url, data, headers)

新しい"バックエンド定義"を作成します。

引数 説明
method

型:string

HTTPメソッドを指定します。

url

型:stringRegExp

HTTPのURLを指定します。

data(optional)

型:stringRegExpfunction(string)

HTTPリクエストのボディ、 またはデータ文字列を受け取り、データが期待通りであればtrueを返す関数のどちらかを指定します。

headers(optional)

型:Objectfunction(Object)

HTTPヘッダー、またはHTTPヘッダーオブジェクトを受け取り、 もしヘッダーが最新の定義とマッチすればtrueを返す関数のどちらかを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

respond – {function([status,] data[, headers]) | function(function(method, url, data, headers)}
返された静的なデータ設定を取得する応答メソッド、またはレスポンスのステータス(数値)、 レスポンスのデータ(文字列)、レスポンスヘッダー(オブジェクト)を含む配列を返すことが出来る関数です。

DELETE用の新しい"バックエンド定義"を作成します。 詳細は、when()を確認してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

headers(optional)

型:Objectfunction(Object)

HTTPヘッダー、またはHTTPヘッダーオブジェクトを受け取り、 もしヘッダーが最新の定義とマッチすればtrueを返す関数のどちらかを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

GET用の新しい"バックエンド定義"を作成します。 詳細は、when()を確認してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

headers(optional)

型:Objectfunction(Object)

HTTPヘッダー、またはHTTPヘッダーオブジェクトを受け取り、 もしヘッダーが最新の定義とマッチすればtrueを返す関数のどちらかを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

whenDELETE(url, headers)

HEAD用の新しい"バックエンド定義"を作成します。 詳細は、when()を確認してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

headers(optional)

型:Objectfunction(Object)

HTTPヘッダー、またはHTTPヘッダーオブジェクトを受け取り、 もしヘッダーが最新の定義とマッチすればtrueを返す関数のどちらかを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

whenGET(url, headers)

JSONP用の新しい"バックエンド定義"を作成します。 詳細は、when()を確認してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

whenHEAD(url, headers)

POST用の新しい"バックエンド定義"を作成します。 詳細は、when()を確認してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

data(optional)

型:stringRegExpfunction(string)

HTTPリクエストのボディ、 またはデータ文字列を受け取り、データが期待通りであればtrueを返す関数のどちらかを指定します。

headers(optional)

型:Objectfunction(Object)

HTTPヘッダー、またはHTTPヘッダーオブジェクトを受け取り、 もしヘッダーが最新の定義とマッチすればtrueを返す関数のどちらかを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

whenJSONP(url)

PUT用の新しい"バックエンド定義"を作成します。 詳細は、when()を確認してください。

引数 説明
url

型:stringRegExp

HTTPのURLを指定します。

data(optional)

型:stringRegExpfunction(string)

HTTPリクエストのボディ、 またはデータ文字列を受け取り、データが期待通りであればtrueを返す関数のどちらかを指定します。

headers(optional)

型:Objectfunction(Object)

HTTPヘッダー、またはHTTPヘッダーオブジェクトを受け取り、 もしヘッダーが最新の定義とマッチすればtrueを返す関数のどちらかを指定します。

戻り値 説明
 

型:requestHandler

一致したリクエストを制御するrespondメソッド付きのオブジェクトを返します。

 Back to top

© 2017 Google
Licensed under the Creative Commons Attribution License 3.0.

このページは、ページトップのリンク先のAngularJS公式ドキュメント内のページを翻訳した内容を基に構成されています。 下記の項目を確認し、必要に応じて公式のドキュメントをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。

  • AngularJSの更新頻度が高いため、元のコンテンツと比べてドキュメントの情報が古くなっている可能性があります。
  • "訳注:"などの断わりを入れた上で、日本人向けの情報やより分かり易くするための追記を行っている事があります。