2012-09-18 28 views
10

Sto provando a scrivere un test unitario per un controller che è annidato, ma non riesco a capire come deridere lo stesso comportamento nel mio test.Test unitario per controllori nidificati

Ho 2 controller:

function FirstController ($scope) { 
    $scope.childs = [{ 
     title : 'Hello, earth!' 
    }]; 
}; 

function SecondController ($scope) { 
    $scope.child.title = $scope.child.title + $scope.$index; 
}; 

E nel mio HTML:

<div data-ng-controller="FirstController"> 
    <div data-ng-repeat="child in childs" data-ng-controller="SecondController"> 
     {{ child.title }} 
    </div> 
</div> 

E questo funziona come previsto (http://jsfiddle.net/tcayp/1/)

I Unittests:

// FirstController 
it('Should have childs', function() { 
    scope = {}; 
    ctrl = new FirstController(scope); 
    expect(scope.childs.length).toBeGreaterThan(0); 
}); 
// SecondController 
it('Should have inherited a child', function() { 
    scope = {}; 
    ctrl = new SecondController(scope); 
    expect(scope.child.title).toEqual('Hello, earth!0'); 
}); 

In il test di SecondController Non riesco a capire come deridere la catena ereditaria da ng-repeat.

risposta

16

Idealmente, con i test unitari ci piacerebbe testare le classi (unità) in isolamento. Testare 2 controller in un test potrebbe essere eccessivo: un test diventerebbe più complesso e più fragile.

Osservando più da vicino l'esempio fornito si potrebbe notare che non si tratta in realtà di testare 2 controller, ma piuttosto di assicurarsi che i dati siano disponibili in ambito genitore. Quindi, concentrandosi su un controller unico (SecondController) ei dati ereditati avrebbe scrivere un test come questo:

describe('Testing the SecondController controller', function() { 

    var $parentScope, $scope, ctrl; 
    it('should prepare title', inject(function($rootScope, $controller) { 

     //setup hierarchy of scopes with data    
     $rootScope.childs = [{ 
      title : 'Hello, earth!' 
     }]; 
     $scope = $rootScope.$new(); 
     $scope.$index = 1; 

     ctrl = $controller('SecondController', { 
      $scope: $scope 
     }); 

     expect($scope.childs[0].title).toEqual('Hello, earth!1');   
    })); 
}); 

Qui è la piena jsFiddle: http://jsfiddle.net/pkozlowski_opensource/h8xry/13/

Vorrei davvero consigliare contro test 2 controller insieme, ma solo per il gusto di rispondere alla domanda, è possibile vedere:

describe('Testing the SecondController controller', function() { 

    it('should prepare title', inject(function($rootScope, $controller) { 

     $controller('FirstController', { 
      $scope: $rootScope 
     }); 

     var $scope = $rootScope.$new(); 
     $scope.$index = 1; 

     ctrl = $controller('SecondController', { 
      $scope: $scope 
     }); 

     expect($scope.childs[0].title).toEqual('Hello, earth!1');   
    })); 
}); 

E il jsFiddle: http://jsfiddle.net/pkozlowski_opensource/4Qy6b/1/

+0

Grazie, l'ho riscritto in modo da utilizzare il primo esempio. – fredrik

2

AngularJS documentation suggerisce di testare i controller nidificati istanziando ciascuno di essi e stabilendo la stessa gerarchia di ambito tra loro come nella propria app. Questo ha senso perché (fino a un certo punto) si desidera testare il controller in un contesto realistico.

1

nel test istanziare il controller genitore con un nuovo ambito:

mainScope = $rootScope.$new(); 
$controller('ParentController', {$scope: mainScope}); 

e il controller del bambino, un'istanza di un nuovo ambito utilizzando il campo di applicazione in precedenza un'istanza:

childScope = mainScope.$new(); 
$controller('ChildController', {$scope: childScope}); 

Esempio dal AngularJS documentation :

describe('state', function() { 

    var mainScope, childScope, grandChildScope; 

    beforeEach(module('myApp')); 

    beforeEach(inject(function($rootScope, $controller) { 
     mainScope = $rootScope.$new(); 
     $controller('MainController', {$scope: mainScope}); 
     childScope = mainScope.$new(); 
     $controller('ChildController', {$scope: childScope}); 
     grandChildScope = childScope.$new(); 
     $controller('GrandChildController', {$scope: grandChildScope}); 
    })); 

    it('should have over and selected', function() { 
     expect(mainScope.timeOfDay).toBe('morning'); 
     expect(mainScope.name).toBe('Nikki'); 
     expect(childScope.timeOfDay).toBe('morning'); 
     expect(childScope.name).toBe('Mattie'); 
     expect(grandChildScope.timeOfDay).toBe('evening'); 
     expect(grandChildScope.name).toBe('Gingerbread Baby'); 
    }); 
});