¿Cómo me burlo de $ location.host () en las testings de angularjs?

Env un service Env que completa la información del entorno, y actualmente estoy usando $location.host() para determinar en qué entorno estoy. ¿Cómo me burlo de eso en mis testings?

He leído https://groups.google.com/forum/?fromgroups#!topic/angular/F0jFWC4G9hI , pero parece que no funciona, por ejemplo:

 describe("Env (environment) service", function() { var Env; beforeEach(module('App')); beforeEach(inject( ['Env', function(e) { Env = e; }] )); describe("for staging", function() { beforeEach(inject(function($location, $rootScope) { $location.host("http://staging-site.com"); $rootScope.$apply(); })); it("returns envrionment as staging", function() { expect(Env.environment).toEqual("staging"); }); it("returns .isStaging() as true", function() { expect(Env.isStaging()).toBeTruthy(); }); }); }); 

También probé la variante de $browser , pero tampoco funciona. ¿Algunas ideas?

La mejor manera es usar espías en mi humilde opinión: http://tobyho.com/2011/12/15/jasmine-spy-cheatsheet/

 // inject $location spyOn($location, "host").andReturn("super.domain.com"); var host = $location.host(); alert(host) // is "super.domain.com" expect($location.host).toHaveBeenCalled(); 

Tuve un problema similar y he usado el service $ injector. (No sé si es la solución más simple, pero funcionó para mí :))

Como no se puede confiar en $ location durante las testings, he preparado mi propio simulacro. Primero, necesitas crear un método de fábrica. (O service o proveedor si lo prefiere, consulte https://gist.github.com/Mithrandir0x/3639232 para comparar):

 function locationFactory(_host) { return function () { return { /* If you need more then $location.host(), add more methods */ host: function () { return _host; } }; }; } 

Luego, antes de crear su 'Env' , inyecte el inyector con este simulador de $ location:

 module(function ($provide) { $provide.factory('$location', locationFactory('http://staging-site.com')); }); 

Ahora, cada vez que se ingresa su location de $ $ en su código, se simula su simulacro, de modo que devuelve lo que necesita. Más sobre el método $ provide es en documentos angulares

Espero que esto te ayude en el futuro.

Actualización: Veo un lugar en el que podría haberse equivocado (o que al less estaría mal en mi solución). Parece que estás iniciando tu module 'Env' (que supongo que calcula los datos inmediatamente) y solo después de esto cambias $ location, lo que podría ser demasiado tarde.

Hay un buen ejemplo en el documento: https://docs.angularjs.org/guide/services

Desea asegurarse de usar $provide antes de crear una instancia del service. Me gusta usar $injector en el caso de testing, para primero decidir la location y luego crear una instancia del service.

  var mockLocation; beforeEach(function() { // control the $location.host() function // which we fake in the testcases. mockLocation = { host: jasmine.createSpy() }; module(function($provide) { $provide.value('$location', mockLocation); }); }); 

entonces

  describe('staging server:', function() { beforeEach(function() { // mockLocation.host.andReturn('http://staging-site.com'); // jasmine 1.x mockLocation.host.and.returnValue('http://staging-site.com'); }); it('returns envrionment as staging', inject(function($injector) { Env = $injector.get('Env'); expect(Env.environment).toEqual('staging'); })); }); 

y

  describe('production server:', function() { beforeEach(function() { // mockLocation.host.andReturn('prod.example.com'); // jasmine 1.x mockLocation.host.and.returnValue('prod.example.com'); }); it('returns envrionment as production', inject(function($injector) { Env = $injector.get('Env'); expect(Env.environment).toEqual('production'); })); }); 

Aquí hay otra forma de burlarse de $ location, con Sinon.js

  locationMock = { path: sinon.spy() }; 

Y una afirmación de ejemplo:

 locationMock.path.should.be.calledWith('/home');