问题 如何在茉莉花测试中模拟角度$资源


我试图测试一个使用angular的$资源的控制器。

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会覆盖它,因为无论如何最终会被调用。 VojtaJína听起来像是可以工作但没有骰子。
  • 温和的绰号。满意但不是很有效。

1490
2018-01-09 16:54


起源



答案:


尝试实例化 $resource 使用以下代码:

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

与其他服务类似,除非它们仍在其他模块中。然后将该模块添加到数组中。

更多信息


6
2018-01-09 17:54



也许我在这里不了解一些事情。我试过这个并得到了同样的结果。我更新了我的原帖以包含您的建议。 - akronymn
事实证明,这个解决方案的问题是$ resource实际上并不是一项服务。这是一家工厂。 docs.angularjs.org/api/ngResource.$resource - akronymn


答案:


尝试实例化 $resource 使用以下代码:

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

与其他服务类似,除非它们仍在其他模块中。然后将该模块添加到数组中。

更多信息


6
2018-01-09 17:54



也许我在这里不了解一些事情。我试过这个并得到了同样的结果。我更新了我的原帖以包含您的建议。 - akronymn
事实证明,这个解决方案的问题是$ resource实际上并不是一项服务。这是一家工厂。 docs.angularjs.org/api/ngResource.$resource - akronymn


经过更多的阅读和更多的实验,似乎正确的方法是从控制器中抽象出$ resource的使用。在我的情况下,我编写了一个依赖于$ resource的服务,然后将该服务注入我的控制器。同时我与我的控制器分开测试该服务。更好地练习四周。

我的服务声明:

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

在我的单元测试中,我在beforeEach设置函数中传递了它

beforeEach(module('apiModule'));

6
2018-01-16 01:37



您能否分享更完整的代码示例?作为Angular和Jasmine的新手,我无法绕过这个问题。 - Petrus Theron
@akronym所以你包括在内 app.js 测试控制器? - Deeptechtons
但是,在测试您的服务时,您是否会遇到同样的问题? - Martin Hansen
你能帮我解决这个问题,它几乎是一样的...... stackoverflow.com/questions/30947701/... - mariowise
@akronymn可以编写完整的代码示例,如何模拟$ resource服务? - Saurabh