我创建了一个包含环境信息的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 :(得分: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();
jasmine 2.0及更高版本的语法已更改如下
// inject $location
spyOn($location, "host").and.returnValue("super.domain.com");
var host = $location.host();
alert(host) // is "super.domain.com"
expect($location.host).toHaveBeenCalled();
答案 1 :(得分:4)
我有类似的问题,并使用了$ injector服务。 (我不知道这是否是最简单的解决方案,但它对我有用:))
由于在测试期间无法依赖$ location我已经准备好了自己的模拟。 首先,您需要创建一个工厂方法。 (如果您愿意,可以选择服务或提供商 - 请参阅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;
}
};
};
}
然后在您创建'Env'之前,使用此$ location mock提供进样器:
module(function ($provide) {
$provide.factory('$location', locationFactory('http://staging-site.com'));
});
现在,每次在代码中访问$ location时,都会注入模拟,因此它会返回您需要的任何内容。 有关$ offer方法的更多信息,请参见angular docs
希望将来能帮到你。
更新:我看到一个地方你可能出错了(或者至少在我的解决方案中错了)。看起来你正在启动你的'Env'模块(我猜它会立即计算出来)并且只有在你改变$ location之后 - 这可能已经太晚了。
答案 2 :(得分:2)
文档中有一个很好的例子: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');
}));
});
答案 3 :(得分:0)
这是使用Sinon.js
模拟$ location的另一种方法 locationMock = {
path: sinon.spy()
};
一个例子断言:
locationMock.path.should.be.calledWith('/home');