2012-09-04 17 views
28

Aquí está el archivo de especificaciones de prueba:Cómo inyectar dependencias en la prueba de jazmín para un elemento angular

describe('Test main controller', function(){ 
     it('Should initialize value to Loading', function(){ 
      $scope = {} 
      ctrl = new mainNavController($scope) 
      expect($scope.wksp_name).toBe('Loading') 
     }) 
    }) 

Aquí está el archivo controlador

function mainNavController($scope) { 
    $scope.wksp_name = 'Loading...' 
    $scope.$on('broadCastWkspNameEvent', function (e, args) { 
     $scope.wksp_name = args 
    }) 
} 

mainNavController.$inject=['$scope'] 

Pero mi prueba falla diciendo Object #<Object> has no method '$on'

Estoy usando la configuración básica de jazmín.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
    <title>Jasmine Spec Runner</title> 

    <link rel="shortcut icon" type="image/png" href="testlib/jasmine-1.2.0/jasmine_favicon.png"> 
    <link rel="stylesheet" type="text/css" href="testlib/jasmine-1.2.0/jasmine.css"> 
    <script type="text/javascript" src="testlib/jasmine-1.2.0/jasmine.js"></script> 
    <script type="text/javascript" src="testlib/jasmine-1.2.0/jasmine-html.js"></script> 

    <!-- include source files here... --> 
    <script type="text/javascript" src="/static_files/js/test-specs/main-nav-spec.js"></script> 

    <!-- include spec files here... --> 
    <script type="text/javascript" src="/static_files/js/common/jquery/latest.js"></script> 
    <script type="text/javascript" src="/static_files/js/common/angular/angular-1.0.1.min.js"></script> 
    <script type="text/javascript" src="/static_files/js/common/angular/angular-resource-1.0.1.min.js"></script> 
    <script type="text/javascript" src="/static_files/js/section/main-nav-controller.js"></script> 

    <script type="text/javascript"> 
    (function() { 
     var jasmineEnv = jasmine.getEnv(); 
     jasmineEnv.updateInterval = 1000; 

     var htmlReporter = new jasmine.HtmlReporter(); 

     jasmineEnv.addReporter(htmlReporter); 

     jasmineEnv.specFilter = function(spec) { 
     return htmlReporter.specFilter(spec); 
     }; 

     var currentWindowOnload = window.onload; 

     window.onload = function() { 
     if (currentWindowOnload) { 
      currentWindowOnload(); 
     } 
     execJasmine(); 
     }; 

     function execJasmine() { 
     jasmineEnv.execute(); 
     } 

    })(); 
    </script> 

</head> 

<body> 
</body> 
</html> 

¿Qué es lo que estoy haciendo mal? No puedo entender cómo se supone que funciona esto :)

Respuesta

57

El principal problema con el código de prueba es que intenta crear una instancia del controlador "a mano" con el nuevo operador. Al hacerlo, AngularJS no tiene posibilidad de inyectar dependencias. Lo que usted debe hacer es permitir AngularJS inyectan dependencias:

var $scope, ctrl; 

//you need to inject dependencies first 
beforeEach(inject(function($rootScope) { 
    $scope = $rootScope.$new();   
})); 

it('Should initialize value to Loading', inject(function($controller) { 
    ctrl = $controller('MainNavController', { 
     $scope: $scope 
    }); 
    expect($scope.wksp_name).toBe('Loading...'); 
})); 

Aquí está el enlace a un jsFiddle completa: http://jsfiddle.net/pkozlowski_opensource/7a7KR/3/

Hay 2 cosas digno de mención en el ejemplo anterior:

  1. Puede usar el método inject() del módulo ngMock para inyectar dependencias: https://docs.angularjs.org/api/ngMock/function/angular.mock.inject
  2. Para crear una instancia de controlador (que admita la inyección de dependencia) usaría $ controll Servicio er: http://docs.angularjs.org/api/ng.$controller

A medida que la última observación: Yo aconsejaría nombrar controladores que comienzan con una letra mayúscula - de esta manera no les hemos de confundir con los nombres de las variables.

3

Estoy de acuerdo con la respuesta del pkozowski, sino para responder a su pregunta de manera más directa, es necesario apagar '$ en'

Su ejemplo pasaría si su $ alcance parecía:

$scope = { 
    $on: function() {} 
} 
+1

o utilizar un espía Jasmine –

16

Gran respuesta por @ pkozlowski.opensource. Para elaborar un poco más ... A veces también podría ser útil afirmar que el controlador realmente llamó a $scope.$on. En este caso se puede espiar a $scope.$on como se señala a continuación:

beforeEach(inject(function($rootScope) { 
    $scope = $rootScope.$new();   
    spyOn($scope, '$on').andCallThrough(); 
})); 

Y entonces se puede afirmar que $on fue llamado con su nombre de evento y alguna función como argumentos:

it('Should bind to "broadCastWkspNameEvent"', inject(function($controller) { 
    ctrl = $controller('MainNavController', { 
     $scope: $scope 
    }); 
    expect($scope.$on).toHaveBeenCalledWith('broadCastWkspNameEvent', jasmine.any(Function)); 
})); 
Cuestiones relacionadas