unitarias test pruebas promesas javascript angularjs unit-testing mocking jasmine

javascript - test - Angular y Jasmine: cómo burlarse de un servicio que devuelve una promesa



test jasmine angular 2 (1)

Tengo el siguiente controlador en AngularJS que invoca un servicio proporcionado por "$ mdSidenav" de Angular Material. Este servicio es proporcionado por un método de fábrica.

angular.module(''leopDirective'', []) .controller(''MenuCtrl'', function ($scope,$timeout,$mdSidenav,$log) { $scope.mdSidenav = $mdSidenav; $scope.close = function () { $mdSidenav(''left'').close().then(function() {$scope.closed=true; }); }; });

Estoy intentando burlarme de ese servicio ($ mdSidenav) para probar mi controlador. El siguiente es el código fuente de la prueba Jasmine que estoy tratando de definir:

describe(''Controller: MenuCtrl'', function() { var $rootScope, $scope, $controller, $q, menuCtrl, mock__mdSidenav = function(component) { return { // THIS FUNCTION IS EMPTY SINCE $Q IS NOT AVAILABLE close: function() {} } }; beforeEach(function() { module(''leopDirective'', function($provide) { // I HAVE TO PROVIDE THE MOCK UP BEFORE INJECTING $Q $provide.value(''$mdSidenav'', mock__mdSidenav); }); inject(function($injector) { $rootScope = $injector.get(''$rootScope''); $controller = $injector.get(''$controller''); $q = $injector.get(''$q''); $scope = $rootScope.$new(); }); menuCtrl = $controller("MenuCtrl", { $scope: $scope }); }); it(''should create the $mdSidenav object'', function() { var deferred = $q.defer(), promise = deferred.promise; // NOW THAT $Q IS AVAILABLE, I TRY TO FILL UP THE FUNCTION mock__mdSidenav.close = function() { return promise.then(function(response){return response.success;}); }; // force `$digest` to resolve/reject deferreds $rootScope.$digest(); // INVOKE FUNCTION TO TEST $scope.close(); }); });

El problema que tengo es que no sé cómo crear una función para el simulacro que devuelva una promesa:

  1. crear una promesa depende de $ q,
  2. $ q tiene que ser inyectado desde dentro del bloque "inyectar",
  3. sin embargo, $ provide debe ser utilizado dentro de "módulo", justo antes de "inyectar",
  4. por lo tanto, la función que devuelve una promesa dentro de mi objeto simulado (mock__mdSidenav (). close ()), tiene que estar vacía antes de invocar "$ provide" y, de alguna manera, crearse más tarde.

Con este enfoque, el error que estoy obteniendo es el siguiente error (ver Demo plnkr ), que me dice que crear primero la función vacía y llenarla más tarde no funciona:

TypeError: Cannot read property ''then'' of undefined at Scope.$scope.close (app.js:7:35)

¿Cuál es la forma correcta de burlarse de un servicio que tiene una función que devuelve una promesa?


En primer lugar, haga que el método de servicio simulado devuelva el objeto Promesa:

mock__mdSidenav = function(component) { return { isMock: true, close: function() { return $q.when(); } } };

A continuación, inyéctelo en la instancia del controlador:

menuCtrl = $controller("MenuCtrl", { $scope: $scope, $mdSidenav: mock__mdSidenav });

Y finalmente, escriba alguna expectativa:

it(''should create the $mdSidenav object'', function() { $scope.close(); $rootScope.$digest(); expect($scope.closed).toBe(true); });

Demostración: http://plnkr.co/edit/dr79GgZYG2tjiuWU0oFx?p=preview