2013-06-12 93 views
6

我创建了一个包装环境信息的Env服务,我目前使用$location.host()来确定我所处的环境。我如何在我的测试中嘲笑它?

我读过https://groups.google.com/forum/?fromgroups#!topic/angular/F0jFWC4G9hI,但它似乎没有工作,例如:

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

我也试过$browser变种,但也不管用。有任何想法吗?

+0

我也试过'$ browser.url()'按http://www.thecssninja.com/javascript/angular位置测试,但这也行不通。 – zlog

+0

我有类似的问题,我需要注入$位置到我的测试,因为服务需要它。 –

+1

https://github.com/angular/angular.js/issues/493 –

回答

4

我有类似的问题,并使用$注射器服务。 (我不知道它是否是最简单的解决方案,但它对我有用:))

由于$位置不能在测试过程中依赖,所以我准备了自己的模拟。 首先,您需要创建一个工厂方法。 (或服务或供应商,如果你喜欢 - 看到https://gist.github.com/Mithrandir0x/3639232比较):

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

然后你这个$位置模拟创建你的“信封”,供给喷射器中之前:

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

现在每在你的代码中注入你的访问$ location的时候,所以它会返回你需要的任何东西。 更多$提供方法是在angular docs

希望这可以帮助你在未来。

更新:我看到一个地方,当你可能出问题了(或者至少在我的解决方案中会出错的地方)。看起来你正在启动你的'Env'模块(我猜想它会立即计算数据),并且只有在这之后你才改变$ location - 这可能已经太晚了。

6

最好的办法是使用间谍恕我直言: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(); 
+1

茉莉花2.0及更高版本的语法已更改,您应该使用.and.returnValue() – wholladay

0

这里是另一种方式来嘲笑$位置,与Sinon.js

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

和示例断言:

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

doc中有一个很好的例子:https://docs.angularjs.org/guide/services

在实例化服务之前,您想确保使用$provide。我喜欢在测试用例中使用$injector,首先决定位置,然后实例化服务。

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

然后

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

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'); 
    })); 
    }); 
相关问题