带有服务的单元测试控制器

Unit test controller with service in it

我正在尝试对注入了服务的控制器进行单元测试。无论我尝试什么,我都会收到错误消息。任何帮助我实现这一目标的帮助将不胜感激。我正在使用 Angular/Karma/Jasmine 获取 运行 我的测试。

似乎有很多帖子具有相似的故事,但这感觉可能不是重复的 - 如果是,请见谅。

我的控制器看起来像这样:

(function() {
  angular
    .module('blah')
    .controller('AdminController', AdminController);

  /* @ngInject */
  function AdminController($scope, toastr, adminService) {
    activate();

    /**
     * Controller initialisation.
     */
    function activate() {
      getAllUsers();
    }

    /**
     * Gets all users.
     */
    function getAllUsers() {
      adminService.getAllUsers()
        .then(function(response) {
          $scope.users = response.data;
        })
        .catch(function(error) {
          toastr.error('Unable to load users', 'Error');
          console.log(error);  
        });
     }        
  }
})();

我的服务是这样的:

(function() {
  angular
    .module('blah')
    .factory('adminService', adminService);

  /* @ngInject */
  function adminService($http, environmentConfig) {
    var service = {
      getAllUsers: getAllUsers
    };

    return service;

    /**
     * Gets all user objects.
     */
    function getAllUsers() {
      return $http.get(environmentConfig.apiBaseUrl + '/user');
    }
  }
})();

我的单元测试是这样的:

describe('AdminController', function() {
  var ctrl,
      adminService,
      $scope;

  var listOfTestUsers = [
    { name: 'Dave', id: 1 },
    { name: 'Bob', id: 2 },
    { name: 'Bill', id:3 }
  ];

  beforeEach(function() {
    module('blah');
  });

  beforeEach(inject(function($rootScope, $controller) {
    adminService = {
      getAllUsers: function() {}
    };

    spyOn(adminService, 'getAllUsers').and.returnValue(listOfTestUsers);

    $scope = $rootScope.$new();

    ctrl = $controller('AdminController', {
      $scope: $scope,
      adminService: adminService
    });
  }));

  describe('The getAllUsers function should exist', function() {
    it('should work', function() {
      expect(ctrl).toBeDefined();
    });
  });
});

我在 运行使用 Karma 测试 Jasmine 时遇到此错误:

TypeError: adminService.getAllUsers(...).then is not a function

您的控制器代码导致了错误。你应该打电话给 $scope.getAllUsers();在你的激活函数中,而不是 "getAllUsers()".

您的实际错误是您的模拟服务没有 'getAllUsers' 功能,这是一个经过调整的粘贴箱 http://pastebin.com/LwG0CzUW

如果您愿意,可以调整测试以调用实际服务作为以下 pastebin。

http://pastebin.com/RSP4RfF9

以下是我发现的一些代码错误。

  1. .catch之前用过。 .then 被调用有两个回调,一个成功回调和一个错误回调。这就是我在您致电 adminService.getAllUsers.

  2. 时所做的
  3. 对于您得到的 TypeError: adminService.getAllUsers(...).then is not a function。您没有正确模拟 getAllUsers 。我已经在 testCases 文件中完成了。它 returns 一个名为 then 的函数,之前不可用。

控制器

(function() {
  angular
    .module('blah', [])
    .controller('AdminController', AdminController);

  /* @ngInject */
  function AdminController($scope, toastr, adminService) {
    $scope.greeting = "Hello World!";

    /**
     * Gets all users.
     */
    $scope.getAllUsers = function() {
      adminService.getAllUsers()
        .then(function(response) {
          $scope.users = response.data;
        }, function(error) {
          toastr.error('Unable to load users', 'Error');
          console.log(error);
        });
    }

    activate();

    /**
     * Controller initialisation.
     */
    function activate() {
      $scope.getAllUsers();
    }
  }
})();

environmentConfig 常量。将其替换为您的。

(function() {
  angular.module('blah').constant('environmentConfig', {
    apiBaseUrl: 'https://www.something.com'
  })
})();

toastr 服务。将其替换为您的

(function() {
  angular
    .module('blah')
    .factory('toastr', toastr);

  /* @ngInject */
  function toastr() {
    var service = {
      error: error
    };

    return service;

    /**
     * Gets all user objects.
     */
    function error(a, b) {
      console.log("Here's the error : ", a);
    }
  }
})();

adminService

(function() {
  angular
    .module('blah')
    .factory('adminService', adminService);

  /* @ngInject */
  function adminService($http, environmentConfig) {

    /**
     * Gets all user objects.
     */
    function getAllUsers() {
      return $http.get(environmentConfig.apiBaseUrl + '/user');
    }

    var service = {
      getAllUsers: getAllUsers
    };

    return service;
  }
})();

测试用例

describe('controller: AdminController', function() {
  var scope, $scope, toastr, adminService, AdminController, flag, $q;
  flag = 'success';

  var listOfTestUsers = [{
    name: 'Dave',
    id: 1
  }, {
    name: 'Bob',
    id: 2
  }, {
    name: 'Bill',
    id: 3
  }];

  beforeEach(module('blah'));

  beforeEach(inject(function($controller, $rootScope, _toastr_, _adminService_, _$q_) {

    scope = $rootScope.$new();
    toastr = _toastr_;
    adminService = _adminService_;
    $q = _$q_;


    spyOn(adminService, 'getAllUsers').and.callFake(function() {
      return flag === 'success' ? $q.when(listOfTestUsers) : $q.reject("Error");
    });

    AdminController = $controller('AdminController', {
      $scope: scope,
      toastr: _toastr_,
      adminService: _adminService_
    });
  }));

  describe('The getAllUsers function should exist', function() {
    it('should work', function() {
      expect(AdminController).toBeDefined();
    });
  });
});

希望对您有所帮助。