Как обмануть angular $ресурс в тестах на жасмин

Я пытаюсь протестировать контроллер, который использует angular $resource.

function PermissionsCtrl($scope, $resource, $cookies) {
  var Object = $resource('/v1/objects/:id');
  loadObjects();

  function loadObjects() {
    $scope.myAppObjects = new Array();

    var data = AppObject.get({find: '{"app_id": '+wtm.app_id+'}'},
      function(){
        if (data.results) {
          for(var i = 0; i< data.results.length; i++) {
            if(!data.results[i].is_deleted) {
              (function(i){
                $scope.objects(data.results[i]);
              }(i));
            }
          }
        }
      },
      function(error){console.log(error);});
  }

И вот тестовый код.

var apiServer = "...";
var app_id = 999
var mock_object_data = {...};


describe('apps permissionsCtrl', function(){
  var scope, ctrl, $httpBackend;

  // Create a matcher for comparing data 
  beforeEach( function() {
    this.addMatchers({
      toEqualData: function(expected) {
        return angular.equals(this.actual, expected);
      }
    });
  });

  // Create the controller with injected data/services
  beforeEach(inject(function(_$httpBackend_, $rootScope, $controller, $resource) {
    $httpBackend = _$httpBackend_;
    // cookie data to inject
    var cookies = new Array();
    cookies['id'] = '...'; // just needs to be declared


    $httpBackend.expectGET(apiServer+'/v1/app_objects?    find=%7B%22app_id%22:'+app_id+'+%7D&access_token=' + cookies['id'])
      .respond( mock_object_data );

    var $injector = angular.injector(['ng', 'ngResource']);
    var $resource = $injector.get('$resource');

    scope = $rootScope.$new();
    ctrl = $controller(PermissionsCtrl, {$scope: scope, $cookies: cookies, $resource: $resource});
  }));

  it('should put object data into $scope', function() {
    $httpBackend.flush();
    expect(scope.objects).toEqualData( mock_object_data );

}); });

Когда я запускаю это, я получаю

Error: Unknown provider: $resourceProvider <- $resource

в строке, где я пытаюсь создать свой контроллер. Я не понимаю, как вводить это в мой контроллер, и независимо от того, что я пытаюсь, я получаю ту же ошибку. Несколько вещей, которые я пробовал, -

  • Объявление пустого макетного объекта и передача его аналогично переменной cookie. Я полагаю, что это, вероятно, плохое решение, так как я действительно хочу использовать эту услугу.
  • Подделка области макета и передача ее в мою функцию ввода и передачу $resource. $new() для моего контроллера.
  • Ничего не делать и надеяться, что httpBackend покроет его с тех пор, что в конечном итоге получится вызвано. Vojta Jína показалось, что это будет работать, но не кубики.
  • Мягкие эпитеты. Удовлетворительно, но не очень эффективно.

Ответ 1

После большего чтения и экспериментов, кажется, правильный способ сделать это - отвлечь использование $resource вне контроллера. В моем случае я написал службу, которая полагается на $resource, а затем внедряет эту службу в мой контроллер. Тем временем я тестирую эту услугу отдельно от своего контроллера. Лучшая практика вокруг.

Объявление моей службы:

angular.module('apiModule', ['localResource', 'ngCookies'])
.factory('apiService', function($resource, $cookies) {

и в моих модульных тестах я передаю его в функции beforeEach setup

beforeEach(module('apiModule'));

Ответ 2

Попробуйте создать экземпляр $resource со следующим кодом:

var $injector = angular.injector(['ng', 'ngResource']);
var $resource = $injector.get('$resource');

Аналогичен для других сервисов, кроме случаев, когда они находятся в других модулях. Затем добавьте этот модуль в массив.

Дополнительная информация