programing

장치 테스트 시 종속 서비스 주입 AngularJS 서비스

stoneblock 2023. 2. 23. 21:59

장치 테스트 시 종속 서비스 주입 AngularJS 서비스

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

표시되는 에러는 다음과 같습니다.

오류: 알 수 없는 공급자: 서비스BProvider

내가 어떻게 이런 일을 할 수 있지?

Angular에서 실제로JS 종속성 주입은 '마지막 승리' 규칙을 사용합니다.따라서 모듈 및 의존관계를 포함한 직후 테스트에서 서비스를 정의할 수 있습니다.테스트 중인 서비스 A가 DI, Angular를 사용하여 서비스 B를 요구할 때JS는 서비스 B의 조롱된 버전을 제공합니다.

이 작업은 MyAppMocks와 같은 새로운 모듈을 정의하고 조롱된 서비스/값을 여기에 추가한 다음 이 모듈을 종속성으로 추가하는 방식으로 수행됩니다.

일종의 (계획적으로):

beforeEach(function() {
  angular.module('MyAppMocks',[]).service('B', ...));
  angular.module('Test',['MyApp','MyAppMocks']);
  ...

CoffeeScript에서 이 작업을 수행하다가 추가 gotcha를 발견했습니다.(또한 이 페이지의 코드는 이해하기 힘들었습니다.)다음으로 완전한 작업 예를 제시하겠습니다.

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

이후 null을 명시적으로 반환하지 않고$provide.value, 나는 계속 받았다.Error: Argument 'fn' is not a function, got ObjectGoogle Groups 스레드에서 답을 찾았습니다.

발렌틴 솔루션은 나에게 효과가 있었지만 다른 대안이 있다.

beforeEach(function () {

    angular.mock.module("moduleThatContainsServiceA", function ($provide) {
                $provide.value('B', ...);
            });
});

그러면 Angular가JS 서비스 A가 의존성 주입에 의해 서비스 B를 요구합니다.모듈로부터의 서비스 B가 아닌 서비스 B의 모형이 제공됩니다.서비스 A가 포함되어 있습니다.

이렇게 하면 서비스를 조롱하기 위해 각도 모듈을 추가로 작성할 필요가 없습니다.

가장 간단한 방법은 서비스 B를 주입하고 조롱하는 것입니다. 예를 들어 서비스 차량은 서비스 엔진에 의존합니다.이제 자동차를 테스트할 때 엔진을 시뮬레이션해야 합니다.

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

언급URL : https://stackoverflow.com/questions/14238490/injecting-dependent-services-when-unit-testing-angularjs-services