19

私のサービスには、次のような関数があります。

addStatement: function(user, action, object) {
            var statement = {
                    user: user,
                    action: action,
                    object: object
            };
            $http({
                method: 'POST', 
                url: '/foo/bar', 
                data: statement, 
                headers: {Authorization: 'Basic YWxhZGRpbjpvcGVuIHNlc2FtZQ=='}
            }).success(function(data) {
                alert("success: " + data);
            });
        }

このメソッドの単体テストを作成したいのですが、どのように機能させるかわかりません。基本的に、送信されたデータが関数パラメーターから正しく作成され、正しいAuthorizationヘッダーが送信されたことをテストしたいと思います。

$ httpBackendの使用方法を読んでいますが、コントローラーのテストの例と、リクエストが行われて返されるときに$scopeで変更されるものだけがあります。私が望むテストを達成する方法はありますか?それとも私は何か間違ったことをしているのですか?

4

2 に答える 2

37

テストサービスはテストコントローラーとそれほど変わらないため、原則は同じです。基本的に、次のことを行う必要があります。

  • テスト対象のオブジェクトを注入します
  • セットアップモック(存在する場合)-ここでは、$httpBackendモックを使用して正しい方向に進んでいます
  • テスト対象のオブジェクトでメソッドを実行し、結果を確認します

サービスメソッドが$httpPOST呼び出しになることをテストした後は、次のようにテストを記述できます(必須ではない部分は省略)。

beforeEach(module('MyApp'));
beforeEach(inject(function(MyService, _$httpBackend_) {
    service = MyService;
    $httpBackend = _$httpBackend_; // angular strips the underscores so
                                   // we don't need to use unique names
    // https://docs.angularjs.org/api/ngMock/function/angular.mock.inject
}));

it('should invoke service with right paramaeters', function() {
    $httpBackend.expectPOST('/foo/bar', {
        "user": "testUser",
        "action": "testAction",
        "object": {}
    }, function(headers){
        return headers.Authorization === 'Basic YWxhZGRpbjpvcGVuIHNlc2FtZQ==';
    }).respond({});
    service.addStatement('testUser', 'testAction', {});
    $httpBackend.flush();
});

これが実際のこのテストを説明する動作中のjsFiddleです:http://jsfiddle.net/pkozlowski_opensource/MkrjZ/2/

最後にもう1つ、ユニットテストでは.alert()を使用しない方がよいでしょう。これらのアラートは、テストの実行を一時停止するからです。

于 2012-08-23T06:39:27.463 に答える
2

私はそのトピックについてブログ投稿を書き、angularの組み込みモックの使用と独自のモックの作成について少し説明しました。おそらくそれはあなたがより深い理解を得るのに役立つでしょう:

AngularJSモジュールをモックして、それらを精巣テストに注入する方法は?

つまり、目的の動作をモックできるテスト用の2番目のモジュールを定義します。

var apptastic      = angular.module('apptastic', []),
    apptasticMock  = angular.module('apptasticMock', []);

そして、元の動作を上書きします。たとえば、次のようになります。

apptasticMock.service("socket", function($rootScope){
... // overwrite
});

次に、テストでロードする必要があります。これは、Angularがすでに定義されているサービスをロードされた順序で上書きするために機能します。

describe("Socket Service", function(){
  var socket;

  beforeEach(function(){
    module('apptastic');
    module('apptasticMock');

    inject(function($injector) {
      socket = $injector.get('socket');
    });
  });

  it("tests something", function(){
  ... // test
  });

});

コードの優れた構造により、継承でさえ実際には問題にはなりませんが、モックするものと元のコードから使用するものをきめ細かく制御できます。

于 2013-03-24T16:08:08.203 に答える