unit testing - test - ¿Cómo puedo probar un controlador con propiedades de resolución en AngularJS?
test unit angular 4 (4)
¿Cómo se puede probar un controlador con propiedades de resolución? Se produce un error: Proveedor desconocido: InitProvider, durante la prueba, de manera comprensible. ¿Cómo puedo probarlo?
Utilizo la propiedad init en la configuración de ruta para cargar datos y pasarlos al controlador en la instanciación del controlador para que la ruta no cambie antes de que se carguen los datos.
$routeProvider
.when(''/topic/:topic_id/content/:content_id'', {
templateUrl: ''views/content.html'',
controller: ''ContentCtrl'',
resolve: {
init: ContentCtrl.init
}
});
¿Es el patrón completamente incorrecto en primer lugar?
''use strict'';
var ContentCtrl = [''$scope'', ''$location'', ''$routeParams'', ''init'', function ($scope, $location, $routeParams, init) {
$scope.contents = init.contents;
}];
ContentCtrl.init = [''$q'', ''app_config'', ''$log'', ''$timeout'', function ($q, app_config, $log, $timeout) {
var defer = $q.defer();
$log.log("ContentCtrl loading..");
$timeout(function() {
defer.resolve({contents: [
{message: ''Hello!''}
]});
$log.log("ContentCtrl loaded.");
}, 2000);
return defer.promise;
}];
angular.module(''studentportalenApp'').controller(''ContentCtrl'', ContentCtrl);
Quiero encapsular todo el controlador dentro de .controler(''ContentCtrl'', function() { ... })
, pero aún tengo que descubrir cómo se hace esto correctamente para que el inicio esté disponible en la configuración de la ruta.
A prueba unitaria de valores resueltos de una ruta:
var resolutionObject = $ injector.invoke ($ route.current. $$ route.resolve.testedObject);
Finalmente, se resolvió convirtiendo todo a servicios, como sugirió charlietfl.
Ejemplo:
Configuración de ruta:
//This helper injects a function with the service
//defined in the initMethod string and returns services.prepare()
var interceptWith = function(initMethod) {
return [initMethod, function(m) {
return m.prepare();
}];
}
$routeProvider
.when(''/foobar/'', {
templateUrl: ''foobar.html'',
controller: ''FoobarCtrl'',
resolve: {
init: interceptWith(''FoobarCtrlInit'')
}
});
La definición del controlador foobar:
angular.module(''fooApp'').controller(''FoobarCtrl'', [''$scope'', ''init'', function ($scope, init) {
$scope.data = init.data;
}])
.service(''FoobarCtrlInit'', [''$q'', ''$timeout'', function ($q, $timeout) {
var _prepare = function() {
var deferred = $q.defer();
//Fake async loading of data
$timeout(function() {
deferred.resolve({data: [''A'',''B'',''C'']});
}, 1000);
return deferred.promise;
}
return {
prepare: _prepare
}
}]);
Para probar esto, uno podría hacer esto:
''use strict'';
describe(''Controller: FoobarCtrl'', function() {
// load the controller''s module
beforeEach(module(''fooApp''));
var FoobarCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function($controller) {
scope = {};
CourseCtrl = $controller(''FoobarCtrl'', {
$scope: scope,
init: {data: [''Testdata A'', ''B'', ''C'']}
});
}));
it(''should attach a list of data to the scope'', function() {
expect(scope.data.length).toBe(3);
});
});
Me encontré con lo mismo aquí. Lo resolví utilizando el enfoque aquí: https://groups.google.com/forum/?fromgroups=#!topic/angular/LzXm-9nwkjY .
Básicamente, me burlé de los datos que normalmente se enviarían utilizando una variable simple y los agregué al controlador en la prueba. En tu caso supongo que se vería algo así como:
var initData = {
contents: [{message: ''Hello!''}]
};
$controller("ContentCtrl", { $scope: ..., init: initData });
Tuve el mismo error en Karma al usar la resolución en $ routeProvider, la arreglé probando mi resolución en la prueba de la unidad para app.js, como esto:
describe("myApp", function() {
beforeEach(module(''myApp''));
it(''should resolve initial values for my Controller'', inject(function( $route ) {
expect($route.routes[''/''].resolve.init).toBeDefined; //or whatever test you want
}));
});
Y luego me burlé del valor en la prueba para mi controlador, como este dentro de la descripción para el controlador:
//mock out the resolved values to isolate controller code
beforeEach(module(function($provide) {
$provide.value(''init'', function() {
return ''whatever data you need to mock'';
});