簡體   English   中英

在單元測試AngularJS服務時注入相關服務

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

參考: https//github.com/angular/angular.js/issues/1635

這對我有用。 關鍵是定義一個要模擬的真實模塊。 調用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM