AngularJS + Karma:在单元测试指令或控制器时重用模拟服务

Edu*_*nal 9 code-reuse unit-testing jasmine angularjs karma-runner

我正在使用AngularJS + Karma. configService管理我的应用程序的设置(例如背景颜色,它在调试模式下,一般权限......).它使用$ http加载初始数据.我成功地为服务编写了测试,但我的指令和控制器使用它.

当我为指令编写单元测试时,我必须模拟服务.

我知道我能做到:

spyOn(configService, 'getBackgroundColor').andCallFake(function (params) {
   return "red";
});
Run Code Online (Sandbox Code Playgroud)

但该服务有25多种方法和初始数据加载.我不想在每个测试套件中编写(并维护)这个spyOn的东西.更重要的是,我使用$ http在工厂加载数据,这也应该被嘲笑.如果我只是注入服务并模拟调用,我仍然会发出http get请求.

您认为重用模拟的最佳方法是什么?

Ste*_*ane 9

您可以在自己的模块中创建适当的服务模拟,并将其添加到需要它的任何测试中,而不是使用间谍喷涂测试代码.

控制器单元测试位于test/spec/modules/user/controller.js文件中.

模拟的服务位于test/mock/modules/user/service.js文件中.

对于控制器方法:

$scope.refreshList = function() {
  UserService.all(pageNumber, size, sort, function(data) {
    $scope.users = data.content;
    $scope.page = data.page;
  });
};
Run Code Online (Sandbox Code Playgroud)

模拟的服务:

(function () {

'use strict';

angular.module('app.user.mock', ['app.user']);

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

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

    factory.search = function(searchTerm, page, size, sort, callback) {
      var defer = $q.defer();
      defer.resolve(this.mockedUsers);
      defer.promise.then(callback);
      return defer.promise;
    };

    factory.all = function(page, size, sort, callback) {
      var defer = $q.defer();
      defer.resolve(this.mockedUsers);
      defer.promise.then(callback);
      return defer.promise;
    };

    return factory;
  }
]);

})();
Run Code Online (Sandbox Code Playgroud)

和控制器单元测试:

(function () {

'use strict';

var $scope;
var listController;
var UserServiceMock;

beforeEach(function() {
  module('app.project');
  module('app.user.mock'); // (1)
});

beforeEach(inject(function($rootScope, _UserServiceMock_) {
  $scope = $rootScope.$new();
  UserServiceMock = _UserServiceMock_; // (2)
}));

describe('user.listCtrl', function() {

  beforeEach(inject(function($controller) {
    listController = $controller('user.listCtrl', {
      $scope: $scope,
      UserService: UserServiceMock
    });
  }));

  it('should have a search function', function () { // (3)
    expect(angular.isFunction(UserServiceMock.search)).toBe(true);
  });

  it('should have an all function', function () {
    expect(angular.isFunction(UserServiceMock.all)).toBe(true);
  });

  it('should have mocked users in the service', function () {
    expect(UserServiceMock.mockedUsers).toBeDefined();
  });

  it('should set the list of users in the scope', function (){
    expect($scope.users).not.toEqual(UserServiceMock.mockedUsers);
    $scope.refreshList();
    $scope.$digest();
    expect($scope.users).toEqual(UserServiceMock.mockedUsers.content);
  });

});

})();
Run Code Online (Sandbox Code Playgroud)

您添加包含模拟服务(1)的app.user.mock模块,并在控制器(2)中注入模拟服务.

然后,您可以测试已注入的模拟服务(3).


Pau*_*tte 0

我创建了一个 .js 文件,其中仅包含一个普通的旧 JavaScript 函数,我调用该函数来创建模拟。另一个普通的旧 JavaScript 函数,用于配置测试的服务器响应。就像你说的,如果你用 json 响应定义一个全局变量,那么你可以在测试中使用它来比较