繁体   English   中英

如何使用Jasmine在AngularJS中为数组函数创建单元测试

[英]How to create unit-testing for array function in AngularJS with Jasmine

我有xf数组: var xf = []; 我有一个函数是此数组中的元素,以及一个使用它的函数:

$scope.checkEmailValid = function () {
  var result = false;
  Iif (xf.validateEmail($scope.email, '256')) {
    result = true;
  }
  return result;
};

xf.validateUsername = function (sText) {
  var isValid = false;
  do {
    //Check for valid string.
    isValid = typeof sText === 'string';
    if (!isValid) {
      break;
    }
    //Check that each special character does not exist in string.
    for (var i = 0; i < sText.length; i++) {
      if (xf.SPECIAL_CHARS.indexOf(sText.charAt(i)) !== -1) {
        isValid = false;
        break;
      }
    }
    if (!isValid) {
      break;
    }
  } while (false);
  return isValid;
};

但是当我运行我的规格时:

it ('checkEmail', function(){
  $controller('MyCtrl', { $scope: $scope });
  xf.validateUsername();
  spyOn(window,xf.validateUsername).and.callThrough();
});

它产生一个错误:

xf.validateUsername不是函数

我该如何掩饰?

xf变量在控制器范围之外是不可取的(即,在单元测试文件中不可访问)。

您必须完成以下操作:

angular
  .module('myModule')
  .controller(function ($scope) {
    var xf = [];
    // etc.
  });

您可以在Angular实例化后将xf变量附加到MyController实例:

angular
  .module('myModule')
  .controller(function ($scope) {
    this.xf = [];
    // etc.
  });

但这并不是真正的干净方法。 (我认为)更好的方法是创建工厂:

angular
  .module('myModule')
  .factory('xfService', function () {
    var xf = [];

    function validateUsername(text) {
      // etc.
    }

    function get() {
      return xf;
    }

    return {
      get: get,
      validateUsername: validateUsername
    };
  });

现在,您可以将工厂注入控制器以使用xf:

angular
  .module('myModule')
  .controller(function ($scope, xfService) {
    // somewhere
    var isValid = xfService.validateEmail($scope.email, '256');
    // to get the values in the array
    var values = xfService.get();
  });

最后,对于单元测试,测试validateEmail方法变得非常容易。

describe('Unit tests - xfService', function () {
  var xfService;
  beforeEach(angular.module('myModule'));
  beforeEach(angular.inject(function (_xfService_) {
      xfService = _xfService_;
    });
  });

  describe('xfService.validateUsername', function () {
    it('should return a boolean value', function () {
      // for example
      expect(typeof xfService.validateUsername('test')).toBe('boolean');
    });
    // add more unit tests to check that the method works as expected
  });
});

您需要将angular-mocks文件添加到Karma配置中。

感谢Paul Podlech和Claies在评论/答案中的提示。

我不确定是否完全理解您的问题。 但有些人认为我认为您做错了:

  • 如果xf是全局变量,则应该模拟它,因为您正在测试控制器,而不是全局变量。
  • 如果要检查全局变量的实函数,请转到karma.conf.js文件,并将js文件路径添加到files选项:

    files: [ ..., 'fx-script.js', ... ],

  • 应该在调用实际函数之前使用callThrough

    it ('checkEmail', function(){ var ctrl = $controller('MyCtrl', { $scope: $scope }); spyOn(window, ctrl.xf.validateUsername).and.callThrough(); ctrl.xf.validateUsername(); });

我建议您分别测试controllerservice或全局脚本,并在需要注入依赖项或全局变量时添加module ,以便您可以随时确定哪个module / script失败。

您应该将xf中的功能移到单独的服务/工厂中。 然后将其注入控制器。 这使得在测试时对其进行模拟非常容易。

在控制器中尝试

var xf = this.xf = [];

这在您的测试中

it ('checkEmail', function(){
 var xf = $controller('MyCtrl', { $scope: $scope }).xf;
 spyOn(xf, 'validateUsername').and.callThrough();
 xf.validateUsername();
});

但是您应该意识到,这正如Claies的评论中提到的那样,将xf对象暴露在Controller上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM