web-dev-qa-db-ja.com

AngularJSでの$ resourceサービスのテスト

angularアプリケーションの単体テストの作成を開始しようとしていますが、テスト可能な方法でサービスをモックする方法が正確にわからないため、非常に迅速に停止ブロックにヒットします。
REST呼び出しをモックする方法はありますか。そうでなければ、自分のテストで自分のサービス内のすべてをミラーリングする必要があるように思えますが、私には正しくないようですがテストライティングはかなり新しいので、おそらくこれが達成されるはずの方法です。

私のサービスは次のとおりです。

angular.module('resources.users', ['ngResource'])
.factory('User', function($resource) {
   var resource = $resource('/api/index.php/users/:username', {}, {
      'update': {method: 'PUT'}
   });

   resource.getUser = function(username, successCb) {
      return resource.query({username: username}, successCb);
   };

   return resource;
});

私のテストは、これまでに次のもので構成されています。

describe('User', function() {
    var mockUserResource;
    beforeEach(module('resources.users'));
    beforeEach(function() {
        mockUserResource = sinon.stub({
            getUser: function(username) {
                mockUserResource.query({username: username});
            },
            query: function() {}
        });
        module(function($provide) {
            $provide.value('User', mockUserResource);
        })
   });
   describe('getUser', function() {
      it('should call getUser with username', inject(function(User) {
          User.getUser('test');
          expect(mockUserResource.query.args[0][0]).toEqual({username: 'test'});
      }));
   })
});
37
Brian

次のように、ngResourceによって行われたリクエストをモックできます。

describe('User', function () {
    var mockUserResource, $httpBackend;
    beforeEach(angular.mock.module('myApp'));

    beforeEach(function () {
        angular.mock.inject(function ($injector) {
            $httpBackend = $injector.get('$httpBackend');
            mockUserResource = $injector.get('User');
        })
    });

    describe('getUser', function () {
        it('should call getUser with username', inject(function (User) {
            $httpBackend.expectGET('/api/index.php/users/test')
                .respond([{
                username: 'test'
            }]);

            var result = mockUserResource.getUser('test');

            $httpBackend.flush();

            expect(result[0].username).toEqual('test');
        }));

    });
});

Demo

54
zs2020

zsongの答え これを理解するのに大いに役立ちましたが、それがどのように機能するかを拡大したいと思います。編集された場合は、ここにコードを再度リストします。

describe('User', function () {
    var mockUserResource, $httpBackend;
    beforeEach(angular.mock.module('myApp'));

    beforeEach(function () {
        angular.mock.inject(function ($injector) {
            $httpBackend = $injector.get('$httpBackend');
            mockUserResource = $injector.get('User');
        })
    });

    describe('getUser', function () {
        it('should call getUser with username', inject(function (User) {
            $httpBackend.expectGET('/api/index.php/users/test')
                .respond([{
                username: 'test'
            }]);

            var result = mockUserResource.getUser('test');

            $httpBackend.flush();

            expect(result[0].username).toEqual('test');
        }));

    });
});

何が起きてる?

1

beforeEach(angular.mock.module('myApp'));

Angular=インジェクター( $injector および angular.mock.inject )に、myAppモジュール:依存モジュールなしでモジュールの依存関係を定義すると考えることができますmyAppモジュールで定義されたものを、たとえばangular.module('myOtherApp', ['myApp'])モジュール。

2

beforeEach(function () {
    angular.mock.inject(function ($injector) {
        $httpBackend = $injector.get('$httpBackend');
        mockUserResource = $injector.get('User');
    })
});

各仕様の前に、依存関係を注入してfunction ($injector)関数を実行します。この場合、依存関係($injector)はパラメーター名から暗黙的に解決されます。このスニペットの機能的に同等のバリアントは

beforeEach(function () {
    angular.mock.inject(['$httpBackend', 'User', function ($httpB, User) {
        $httpBackend = $httpB;
        mockUserResource = User;
    }]);
});

ここでは、依存関係を明示的に宣言しており、希望するパラメーター名を自由に使用できます。

3

it('should call getUser with username', inject(function (User) {

繰り返しますが、テスト関数には、暗黙的に解決されたUserサービスがパラメーターとして挿入されますが、実際には使用されません。

今回はinject呼び出しの周りにラッパー関数がないことに注意してください。 injectは、仕様が現在実行中の場合、渡された関数をすぐに呼び出しますが、そうでない場合はラッパー関数を返します(注入 docs および ソースコード を参照)。実際にはラッパー関数は必要ありません。したがって、上記のbeforeEachスニペットを次のように記述できます。

beforeEach(angular.mock.inject(function ($injector) {
    $httpBackend = $injector.get('$httpBackend');
    mockUserResource = $injector.get('User');
}));
30
Emil Lundberg