如何模拟带参数的Angular服务方法

时间:2015-07-06 13:32:47

标签: javascript angularjs unit-testing jasmine promise

我试图测试我的Angular控制器并需要模拟几个服务才能这样做。我会集中讨论这个问题中的一项服务,其余功能类似。我使用依赖注入来获取playersService,并在我的控制器中使用它:

angular.module('gameApp')
  .controller('PlayerInfoController', PlayerInfoController);

PlayerInfoController.$inject = ['$scope', '$routeParams', 'playersService'];

function PlayerInfoController($scope, $routeParams, playersService) {
  var vm = this;
  var playerId = $routeParams.playerId;

  playersService.getDetails({
    playerId: playerId
  }).$promise.then(function(details) {
    vm.details = details;
  });
}

相关服务如下:

angular.module('gameApp')
  .factory('playersService', ['$resource',
    function($resource) {
      var base = '/api/players/:playererId/';
      return $resource(base, {}, {
        getDetails: {method: 'GET', url: base + 'details'}
      });
    }]);

以下是我当前的单元测试设置失败,出现以下错误:TypeError: 'undefined' is not an object (evaluating 'playersService.getDetails({playerId: playerId}).$promise.then')

describe('PlayerInfoController', function() {
  var scope;
  var routeParams;
  var playersService;

  beforeEach(function() {
    var mockPlayersService = {};
    module('gameApp', function($provide) {
      $provide.value('playersService', mockPlayersService);
    });
    inject(function($q) {
      mockPlayersService.details = {
        'firstName': 'John',
        'lastName': 'Doe',
        'country': 'US'
      };

      mockPlayersService.getDetails = function(playerId) {
        var defer = $q.defer();
        defer.resolve(this.details);
        return defer.promise;
      };
    });
  });

  beforeEach(inject(function($controller, $rootScope, _$routeParams_, _playersService_) {
    scope = $rootScope.$new();
    routeParams = _$routeParams_;
    playersService = _playersService_;

    $controller('PlayerInfoController', {$scope: scope, $routeParams: routeParams, playersService: playersService});

    scope.$digest();
  }));

  it('should say 2 === 2', function() {
    expect(2).toEqual(2);
  });
});

1 个答案:

答案 0 :(得分:2)

playersService.getDetails通常会返回一个带有$ promise属性的相对空对象,一旦调用完成,该对象就会填充结果。

你的mockPlayersService.getDetails需要返回一个类似的对象,所以这样的事情应该这样做:

SELECT [dbo].[RGN].PRIMARY_FLAG
FROM [dbo].[RGN]
JOIN
(SELECT DISTINCT [dbo].[RGN_FAC].RGN_ID
 FROM [dbo].[RGN_FAC]
 WHERE [dbo].[RGN_FAC].FAC_ID = 'my fac id')
ON [dbo].[RGN].ID = [dbo].[RGN_FAC].RGN_ID

作为一个注释,根据角度文档,您通常使用这样的服务(第二个参数可以是调用成功而不是使用$ promise的函数)。

DISTINCT

这也需要你修改你的模拟服务。