如何使用Jasmine为Angular.js的服务和控制器创建测试?

时间:2015-05-25 14:59:31

标签: javascript angularjs jasmine

我有Angular服务和控制器可以正常工作,我无法正确地为它们创建测试。我一直在寻找解决方案。

我的控制器:

angular.module('wideCmsAngularApp').controller('UserListCtrl', [
  '$scope',
  'userService',
  '$routeParams',
  function ($scope, userService, $routeParams) {

    // Get quantity and offset from url. Format: /user/list/10/0
    var quantity = typeof $routeParams.quantity !== 'undefined' ? $routeParams.quantity : 10;
    var offset   = typeof $routeParams.offset !== 'undefined' ? $routeParams.offset : 0;

    $scope.users = userService.query({
      'param1' : quantity,
      'param2' : offset
    });

  }
]);

它使用的服务:

angular.module('wideCmsAngularApp').factory('userService', [
  '$resource',
  function ($resource) {

    return $resource('http://localhost:1337/api/v1/user/:param1/:param2', {}, {
      'get'    : {method : 'GET'},
      'save'   : {method : 'POST'},
      'query'  : {method : 'GET', isArray:true},
      'remove' : {method : 'DELETE'},
      'delete' : {method : 'DELETE'}
    });
  }
]);

控制器的测试:

describe('UserListCtrl', function() {

  beforeEach(module('wideCmsAngularApp'));

  var $controller;
  var $rootScope;
  var userService;

  beforeEach(inject(function(_$rootScope_, _$controller_, _userService_){
    // The injector unwraps the underscores (_) from around the parameter names when matching
    $controller = _$controller_;
    $rootScope  = _$rootScope_;
    userService = _userService_;
  }));

  describe('when asking for a list of users', function() {
    it('should return 4 users', function() {

      var $scope = [];
      var controller = $controller('UserListCtrl', {
        '$scope': $scope,
        'userService': userService,
        '$routeParams': {
          'quantity' : 10,
          'offset'   : 0
        }
      });

      expect($scope.users.length).toBe(4);
    });
  });
});

结果(应返回有4个用户的用户数组,但始终为空):

PhantomJS 1.9.8 (Mac OS X) UserListCtrl when asking for a list of users should return 4 users FAILED
    Expected 0 to be 4.
        at /somewhere/test/spec/controllers/user/list.js:31

我在这里缺少什么?

- UPDATE -

我能够这样做,虽然这不是我真正想要的,因为我更喜欢实际的API请求。这是可能的,还是我必须忍受假的回应?

新的UserListCtr测试,使用$ httpBackend:

var $httpBackend;
var $controller;
var $rootScope;
var userService;

describe('UserListCtrl', function() {

  beforeEach(module('wideCmsAngularApp'));

  beforeEach(inject(function ($injector) {

    var uri = 'http://localhost:1337/api/v1/user/10/0';
    var users = [
      {
        "id": "555daff2862a513508a52ecd",
        "name": "Gru"
      },
      {
        "id": "555daff3862a513508a52ece",
        "name": "Kevin"
      },
      {
        "id": "555daff3862a513508a52ece",
        "name": "Ed"
      },
      {
        "id": "555daff3862a513508a52ece",
        "name": "Tim"
      }
    ];

    httpBackend = $injector.get('$httpBackend');
    httpBackend.whenGET(uri).respond(users)

    $controller = $injector.get('$controller');
    $rootScope  = $injector.get('$rootScope');
    userService = $injector.get('userService');
  }));

  describe('when asking for a list of users', function() {
    it('should return 4 users', function() {

      var $scope = $rootScope.$new();
      var controller = $controller('UserListCtrl', {
        '$scope': $scope,
        'userService': userService,
        '$routeParams': {
          'quantity' : 10,
          'offset'   : 0
        }
      });

      httpBackend.flush();

      expect($scope.users.length).toBe(4);
    });
  });
});

2 个答案:

答案 0 :(得分:2)

您应该使用量角器进行端到端测试。如果你想要一个真正的响应来自服务器,而不是使用httpbackend。

答案 1 :(得分:1)

    angular.module('wideCmsAngularApp').factory('userService', [
      '$resource',
      function ($resource) {

        return $resource('http://localhost:1337/api/v1/user/:param1/:param2', {}, {
          'get'    : {method : 'GET'},
          'save'   : {method : 'POST'},
          'query'  : {method : 'GET', isArray:true},
          'remove' : {method : 'DELETE'},
          'delete' : {method : 'DELETE'}
        });
      }
    ]);

如果我们查看第4行$resource('http://localhost:1337/api/v1/:param1/:param2', {}, {,您会发现您已经通过了三个参数,即URL,paramDefaults和操作,没有通过任何paramDefaults。在{}之后:param2',表示您的paramDefaults已在控制器中设置;

$scope.users = userService.query({
      'param1' : quantity,
      'param2' : offset
    });

您需要将这些内容传递到$resource

$resource Docs