Подтвердить что ты не робот

Тестирование сервисов $resource в AngularJS

Я пытаюсь начать писать модульные тесты для моего приложения 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'});
      }));
   })
});
4b9b3361

Ответ 1

Вы можете высмеивать запросы, сделанные 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');
        }));

    });
});

Демо

Ответ 2

ответ 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');
}));