2012-09-18 31 views
10

Estoy intentando escribir una prueba unitaria para un controlador que está anidado, pero no puedo averiguar cómo simular el mismo comportamiento en mi prueba.Prueba unitaria para controladores anidados

tengo 2 controladores:

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

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

Y en mi HTML:

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

y esto funciona como se esperaba (http://jsfiddle.net/tcayp/1/)

Los 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'); 
}); 

En la prueba SecondController No puedo averiguar cómo simular la cadena heredada de ng-repeat.

Respuesta

16

Idealmente, con pruebas unitarias nos gustaría probar las clases (unidades) de forma aislada. Controlar el controlador 2 en una prueba podría ser demasiado: una prueba se volvería más compleja y más frágil.

Mirando más de cerca el ejemplo proporcionado, uno podría notar que realmente no se trata de probar 2 controladores sino más bien de asegurarse de que los datos estén disponibles en un ámbito principal. Por lo tanto, centrarse en un controlador sólo (SecondController) y los datos heredados uno escribiría una prueba como esta:

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

Aquí es el jsFiddle completo: http://jsfiddle.net/pkozlowski_opensource/h8xry/13/

yo realmente desaconsejar la prueba 2 controladores juntos, pero por el simple hecho de responder a la pregunta, es posible así:

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

Y el jsFiddle: http://jsfiddle.net/pkozlowski_opensource/4Qy6b/1/

+0

Gracias, lo reescribí para que use su primer ejemplo. – fredrik

2

AngularJS documentation sugiere probar controladores anidados instanciando cada uno de ellos y estableciendo la misma jerarquía de alcance entre ellos que en su aplicación. Esto tiene sentido porque (hasta cierto punto) desea probar su controlador en un contexto realista.

1

En la prueba de una instancia del controlador padre con un nuevo ámbito de aplicación:

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

y en su controlador niño, una instancia de un nuevo ámbito de aplicación usando el alcance anteriormente instanciado:

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

Ejemplo de la 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'); 
    }); 
}); 
Cuestiones relacionadas