2013-06-12 130 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'); 
    })); 
    }); 
相關問題