Javascript 角度单元测试:调用另一个控制器中定义的方法是抛出';未定义';这不是一个错误

Javascript 角度单元测试:调用另一个控制器中定义的方法是抛出';未定义';这不是一个错误,javascript,angularjs,jasmine,karma-runner,Javascript,Angularjs,Jasmine,Karma Runner,我试图测试AngularJS文件,但它不能调用在另一个控制器中定义的方法 在MyPage文件中: angular.module('MyApplication').controller('MyPageCtrl', function ($scope, $rootScope) { if($scope.pageChecker) { $scope.doSomething(); } } pageChecker()方法在App.js中的MyApplication controller中定义,

我试图测试AngularJS文件,但它不能调用在另一个控制器中定义的方法

在MyPage文件中:

angular.module('MyApplication').controller('MyPageCtrl', function ($scope, $rootScope) {
  if($scope.pageChecker) {
    $scope.doSomething();
  }
}
pageChecker()方法在App.js中的MyApplication controller中定义,并返回true或false

为了完整起见:

$scope.pageChecker = function() {
  if(cookieCheck) {
    return true;
  }
  else {
    return false;
  }
};
jasmine文件是:

describe("Page check", function(){
  beforeEach(angular.mock.module('MyApplication'));

  beforeEach(angular.mock.inject(function ($rootScope, $controller) {
    var $scope = $rootScope.$new();
    $controller('MyPageCtrl', { $scope: $scope});
  }));

  it("should call $scope.doSomething", function(){
    spyOn($scope, "doSomething");
    $scope.doSomething();
    expect($scope.doSomething).toHaveBeenCalled();
  });
});
我得到“TypeError:“undefined”不是函数(计算“$scope.pageChecker()”)

我想重写pageChecker方法以始终返回true。我该怎么做

编辑:多亏了Dskh,我有了我的答案,还有一个小改动:

describe("Page check", function(){

  var $scope; //declare here, else it is a local variable inside the beforeEach

  beforeEach(angular.mock.module('MyApplication'));

  beforeEach(angular.mock.inject(function ($rootScope, $controller) {
    $scope = $rootScope.$new();
    // define the overriding methods here
    $scope.pageChecker = function(){
      return true;
    };
    // end overriding methods here
    $controller('MyPageCtrl', { $scope: $scope});
  }));

  it("should call $scope.doSomething", function(){
    spyOn($scope, "doSomething");
    $scope.doSomething();
    expect($scope.doSomething).toHaveBeenCalled();
  });
});

在执行$rootScope.$new()时,您自己创建$scope,然后在使用$controller()方法时将其注入到您创建的控制器中

因此,如果希望该方法始终返回true,则只需自己创建该方法:

beforeEach(angular.mock.inject(function ($rootScope, $controller) {
    var $scope = $rootScope.$new();

    $scope.doSomething = function(){
        return true;
    };

    $controller('MyPageCtrl', { $scope: $scope});
  }));

还有一些解释:当你的应用程序真正运行时,$scope会被angular自动注入到你的控制器中。在你的测试中,你只是孤立地测试你的控制器,所以你需要自己创建scope对象并伪造你想要的任何行为。使用$rootScope()。$new()将为您提供$watch或$on等角度方法,但您需要自己重新创建自己的方法。

我认为问题中有输入错误,我没有看到对$scope.pageChecker()的任何调用作为函数调用。看起来您的控制器调用$scope.pageChecker方法作为控制器实例化的一部分,当您在测试中在控制器创建中提供范围对象时,它确实没有pageChecker方法良好的catch,Eitan,但不是问题的原因。这是一个names-have-been-changed-to-protect-t他是我代码的无辜版本,因为我的雇主不希望我发布实际代码。:)谢谢你Dskh。这就成功了,因为我还发现我必须将$scope设置为全局变量。这阻止了我正确定义$scope,因为我将其定义为局部变量。噢!