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

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

本文关键字:数组 函数 单元测试 创建 何用 Jasmine AngularJS      更新时间:2023-09-26

我有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;
};
但是当我运行spec:
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.
  });

你可以把xf变量附加到MyController实例中,一旦Angular实例化了它:

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在评论/回答中的提示。

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

    如果它是一个全局变量,你应该模拟它,因为你是在测试控制器,而不是全局变量。
  • 如果你想检查全局变量的实际功能,转到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或全局脚本,并在需要注入依赖项或全局变量时添加mock,这样您就可以确定哪个module/script在任何时候都失败。

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

在控制器中试试

var xf = this.xf = [];

在你的测试

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

但是您应该意识到,这暴露了控制器上的xf对象,正如claes注释中提到的。