[英]Injecting dependent services when unit testing AngularJS services
我正在測試服務A,但服務A依賴於服務B(即服務B注入服務A)。
我已經看到了這個問題,但我的情況有點不同,因為在我看來, 模擬服務B而不是注入服務B的實際實例更有意義。我用茉莉花間諜嘲笑它。
這是一個示例測試:
describe("Sample Test Suite", function() {
beforeEach(function() {
module('moduleThatContainsServiceA');
inject([
'serviceA', function(service) {
this.service = service;
}
]);
});
it('can create an instance of the service', function() {
expect(this.service).toBeDefined();
});
});
我得到的錯誤是:
錯誤:未知提供者:serviceBProvider
我怎么能這樣做?
實際上在AngularJS中,依賴注入使用“最后獲勝”規則。 因此,您可以在包含模塊和依賴項之后立即在測試中定義服務,然后當您正在測試的服務A將使用DI請求服務B時,AngularJS將提供服務B的模擬版本。
這通常是通過定義像MyAppMocks這樣的新模塊,將模擬服務/值放在那里然后只是將此模塊添加為依賴項來完成的。
種類(示意圖):
beforeEach(function() {
angular.module('MyAppMocks',[]).service('B', ...));
angular.module('Test',['MyApp','MyAppMocks']);
...
我在CoffeeScript中這樣做,發現了額外的問題。 (另外,我發現這個頁面上的代碼容易混淆。)這是一個完整的工作示例:
describe 'serviceA', ->
mockServiceB = {}
beforeEach module 'myApp' # (or just 'myApp.services')
beforeEach ->
angular.mock.module ($provide) ->
$provide.value 'serviceB', mockServiceB
null
serviceA = null
beforeEach inject ($injector) ->
serviceA = $injector.get 'serviceA'
it 'should work', ->
expect( true ).toBe( true )
#serviceA.doStuff()
在$provide.value
之后沒有顯式返回null,我不斷得到Error: Argument 'fn' is not a function, got Object
。 我在此Google網上論壇帖子中找到了答案。
Valentyn解決方案對我有用,但還有另一種選擇。
beforeEach(function () {
angular.mock.module("moduleThatContainsServiceA", function ($provide) {
$provide.value('B', ...);
});
});
然后,當AngularJS服務A通過依賴注入請求服務B時,將從moduleThatContainsServiceA提供服務B的模擬而不是服務B.
這樣,您無需為了模擬服務而創建額外的角度模塊。
我發現最簡單的方法就是注入服務B並模擬它。 例如服務車取決於服務引擎。 現在我們需要在測試Car時模擬Engine:
describe('Testing a car', function() {
var testEngine;
beforeEach(module('plunker'));
beforeEach(inject(function(engine){
testEngine = engine;
}));
it('should drive slow with a slow engine', inject(function(car) {
spyOn(testEngine, 'speed').andReturn('slow');
expect(car.drive()).toEqual('Driving: slow');
}));
});
這對我有用。 關鍵是定義一個要模擬的真實模塊。 調用angular.mock.module使真實模塊可以模擬,並允許連接事物。
beforeEach( ->
@weather_service_url = '/weather_service_url'
@weather_provider_url = '/weather_provider_url'
@weather_provider_image = "test.jpeg"
@http_ret = 'http_works'
module = angular.module('mockModule',[])
module.value('weather_service_url', @weather_service_url)
module.value('weather_provider_url', @weather_provider_url)
module.value('weather_provider_image', @weather_provider_image)
module.service('weather_bug_service', services.WeatherBugService)
angular.mock.module('mockModule')
inject( ($httpBackend,weather_bug_service) =>
@$httpBackend = $httpBackend
@$httpBackend.when('GET', @weather_service_url).respond(@http_ret)
@subject = weather_bug_service
)
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.