试图为AngularJS单元测试提供服务承诺

时间:2015-04-14 09:58:20

标签: angularjs unit-testing karma-jasmine

我正在尝试对工厂进行单元测试:

angular.module('app.user').factory('UserService',
  ['RESTService', 'RESTHTTPService',
  function(RESTService, RESTHTTPService) {
    var factory = {};

    factory.search = function(searchTerm, page, size, sort, callback) {
      return RESTService.User.search({searchTerm: searchTerm, page: page, size: size, sort: sort}).$promise.then(callback);
    };

    return factory;
  }
]);

所以我需要模拟它的RESTService依赖。

angular.module('app.user.mock').factory('RESTService',
  ['$q',
  function($q) {
    var factory = { User: {} };

    factory.allUsers = {
      content: [ { firstname: 'Spirou', lastname: 'Fantasio', email: 'spirou@yahoo.se', workPhone: '983743464365' } ],
      page: '1'
    };

    factory.User.search = function() {
      var defer = $q.defer();
      defer.resolve(factory.allUsers);
      return defer;
    };

    return factory;
  }
]);

用于我的单元测试:

describe('user service repository', function() {

  beforeEach(function() {
    module('com.nsn.nitro.project');
    module('app.utils.mock');
  });

  var UserService;
  var RESTService;

  beforeEach(inject(function(_UserService_, _RESTService_) {
    UserService = _UserService_;
    RESTService = _RESTService_;
  }));

  it('should return the list of users', function () {
    var users = null;
    UserService.search('TOTO', 1, 10, 'asc', function(data) {
      users = data.content;
    });
    expect(users).toEqual(RESTService.allUsers.content);
  });

});

但它给了我错误:

TypeError: Cannot read property 'then' of undefined
        at Object.factory.all (/home/stephane/dev/js/projects/angularjs/nitro-project/app/modules/user/service/repository.js:29:81)
        at null.<anonymous> (/home/stephane/dev/js/projects/angularjs/nitro-project/test/spec/modules/user/service.js:59:17)

模拟的RESTService在UserService中注入良好,但promise属性或$ promise属性未定义。

由于代码在生产中运行良好,我不想触及现有的UserService和RESTService工厂。如果可能的话。

2 个答案:

答案 0 :(得分:1)

$ q&#39;承诺没有名为$ promise的财产。您可以设置一个引用promise属性:

factory.User.get = function() {
  var defer = $q.defer();
  defer.resolve(this.allUsers);
  defer.$promise = defer.promise;
  return defer;
};

另外,由于测试是异步的,您可能需要使用jasmine完成的parmater(取决于您的版本):

it('should return the list of users', function (done) {
    var users = null;
    UserService.all(1, 10, 'asc', function(data) {
      users = data.content;
      expect(users).toEqual(RESTService.allUsers.content);
      done();
    });      
});

答案 1 :(得分:0)

要让测试通过,我需要做两件事:

1-添加$ rootScope。$ digest();在服务电话后:

  it('should return the list of searched users', function() {
    var users = null;
    UserService.search('TOTO', 1, 10, 'asc', function(data) {
      users = data.content;
    });
    $rootScope.$digest();
    expect(users).toEqual(RESTService.allUsers.content);
  });

2-添加$ httpBackend.whenGET(/。html $ /)。回复(&#39;&#39;);解决httpBackend生成对ui-router模板的调用问题。我在How to avoid the 'Error: Unexpected request: GET' every time an AngularJS test does a rootScope.digest() or httpBackend.flush()

的另一个主题中讨论了这个问题
  beforeEach(inject(function(_$httpBackend_, _$rootScope_, _UserService_, _RESTService_) {
    $httpBackend = _$httpBackend_;
    $rootScope = _$rootScope_;
    UserService = _UserService_;
    RESTService = _RESTService_;

    // Always use this statement so as to avoid the error from the $http service making a request to the application main page
    $httpBackend.whenGET(/\.html$/).respond('');
  }));