Тестване на ъглова единица: Извикването на метод, дефиниран в друг контролер, хвърля „недефинирано“ не е грешка

Опитвам се да тествам AngularJS файл, но той не може да извика метод, дефиниран в друг контролер.

Във файла MyPage:

angular.module('MyApplication').controller('MyPageCtrl', function ($scope, $rootScope) {
  if($scope.pageChecker) {
    $scope.doSomething();
  }
}

Методът pageChecker() е дефиниран в App.js, в контролера MyApplication, и връща true или false.

За пълнота:

$scope.pageChecker = function() {
  if(cookieCheck) {
    return true;
  }
  else {
    return false;
  }
};

Файлът жасмин е:

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();
  });
});

person Jezcentral    schedule 02.01.2014    source източник
comment
Мисля, че има правописна грешка във въпроса, не виждам никакво извикване на $scope.pageChecker() като извикване на функция. Изглежда, че вашият контролер извиква метода $scope.pageChecker като част от инстанцията на контролера и когато предоставяте обекта на обхвата при създаването на контролер в теста, той наистина няма метод pageChecker   -  person Eitan Peer    schedule 02.01.2014
comment
Добър улов, Ейтан, но не е причината за проблема. Това беше имената-са-бяха-променени-за-защита-невинните-версия на моя код, тъй като моят работодател не би искал да публикувам действителен код. :)   -  person Jezcentral    schedule 02.01.2014


Отговори (1)


Вие сами създавате $scope, когато правите $rootScope.$new(), и след това го инжектирате в контролера, който създавате, когато използвате метода $controller().

Следователно, ако искате този метод винаги да връща true, просто трябва сами да създадете метода:

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

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

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

Още малко обяснение: Когато приложението ви работи реално, $scope се инжектира автоматично във вашия контролер от angular. Във вашия тест вие просто тествате вашия контролер изолирано, така че трябва сами да създадете обекта на обхвата и да фалшифицирате всяко поведение, което искате от него. Използването на $rootScope().$new() ще ви даде ъглови методи като $watch или $on, но трябва сами да пресъздадете вашите собствени методи.

person Dan    schedule 02.01.2014
comment
Благодаря ти Dskh. Това свърши работа, след като разбрах, че трябва да задам $scope като глобална променлива. Това ме спираше да дефинирам правилно $scope, тъй като го дефинирах като локална променлива. Ох! - person Jezcentral; 02.01.2014