IT

AngularJS 서비스에 모의 배치

lottoking 2020. 7. 24. 07:26
반응형

AngularJS 서비스에 모의 배치


AngularJS 서비스를 작성하는 단위 테스트를 원합니다.

angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
    factory('myService', function ($http, fooService, barService) {

    this.something = function() {
        // Do something with the injected services
    };

    return this;
});

내 app.js 파일에는 다음이 등록되어 있습니다.

angular
.module('myApp', ['fooServiceProvider','barServiceProvider','myServiceProvider']
)

DI가 다음과 같이 작동하는지 테스트 할 수 있습니다.

describe("Using the DI framework", function() {
    beforeEach(module('fooServiceProvider'));
    beforeEach(module('barServiceProvider'));
    beforeEach(module('myServiceProvder'));

    var service;

    beforeEach(inject(function(fooService, barService, myService) {
        service=myService;
    }));

    it("can be instantiated", function() {
        expect(service).not.toBeNull();
    });
});

이것은 DI 프레임 워크에 의해 서비스가 생성 될 수 있음을 증명했지만 다음에는 서비스를 단위 테스트하고 싶습니다.

이 작업은 어떻게합니까?

모의 수업을 모듈에 많이 보았다.

beforeEach(module(mockNavigationService));

서비스 정의를 다음과 같이 다시 작성하십시오.

function MyService(http, fooService, barService) {
    this.somthing = function() {
        // Do something with the injected services
    };
});

angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
    factory('myService', function ($http, fooService, barService) { return new MyService($http, fooService, barService); })

그러나 후자는 DI에 의해 생성되는 서비스를 완전히 중단하는 것처럼 보입니다.

단위 테스트를 위해 제공되는 서비스를 어떻게 조롱 할 수 있는지 아는 사람이 있습니까?

감사합니다

데이비드


를 사용하여 모의를 서비스에 배치 할 수 있습니다 $provide.

getSomething이라는 메소드가있는 메소드가있는 다음 서비스가있는 경우 :

angular.module('myModule', [])
  .factory('myService', function (myDependency) {
        return {
            useDependency: function () {
                return myDependency.getSomething();
            }
        };
  });

다음과 같이 mock 버전의 myDependency를 제공 할 수 있습니다.

describe('Service: myService', function () {

  var mockDependency;

  beforeEach(module('myModule'));

  beforeEach(function () {

      mockDependency = {
          getSomething: function () {
              return 'mockReturnValue';
          }
      };

      module(function ($provide) {
          $provide.value('myDependency', mockDependency);
      });

  });

  it('should return value from mock dependency', inject(function (myService) {
      expect(myService.useDependency()).toBe('mockReturnValue');
  }));

});

호출로 인해 $provide.value실제로 어디에도 myDependency를 명시 적으로 주입 할 필요가 없습니다. myService를 삽입하는 동안 내부에서 발생합니다. 여기서 mockDependency를 설정할 때 스파이처럼 쉽게 할 수 있습니다.

훌륭한 비디오 링크 를 제공 해준 loyalBrown 에게 감사드립니다 .


제가보기에는 서비스 자체를 조롱 할 필요가 없습니다. 서비스의 기능을 조롱하기 만하면됩니다. 이렇게하면 앱 전체에서하는 것처럼 실제 서비스를 각도 주입 할 수 있습니다. 그런 다음 Jasmine의 spyOn기능을 사용하여 필요에 따라 서비스의 기능을 모의합니다 .

이제 서비스 자체가 함수이고 spyOn함께 사용할 수있는 객체가 아니라면 다른 방법이 있습니다. 이 작업을 수행해야했고 나에게 잘 맞는 것을 찾았습니다. 함수 인 Angular 서비스를 어떻게 모의합니까?를 참조하십시오 .


Angular 및 Jasmine에서 종속성을 모의하는 데 도움이되는 또 다른 옵션은 QuickMock을 사용하는 것입니다. GitHub에서 찾을 수 있으며 재사용 가능한 방식으로 간단한 모의를 만들 수 있습니다. 아래 링크를 통해 GitHub에서 복제 할 수 있습니다. README는 꽤 자명하지만 앞으로 다른 사람들에게 도움이되기를 바랍니다.

https://github.com/tennisgent/QuickMock

describe('NotificationService', function () {
    var notificationService;

    beforeEach(function(){
        notificationService = QuickMock({
            providerName: 'NotificationService', // the provider we wish to test
            moduleName: 'QuickMockDemo',         // the module that contains our provider
            mockModules: ['QuickMockDemoMocks']  // module(s) that contains mocks for our provider's dependencies
        });
    });
    ....

위에서 언급 한 모든 상용구를 자동으로 관리하므로 모든 테스트에서 모의 ​​주입 코드를 모두 작성할 필요가 없습니다. 도움이되기를 바랍니다.


John Galambos의 답변 외에도 서비스의 특정 방법을 조롱하고 싶다면 다음과 같이 할 수 있습니다.

describe('Service: myService', function () {

  var mockDependency;

  beforeEach(module('myModule'));

  beforeEach(module(function ($provide, myDependencyProvider) {
      // Get an instance of the real service, then modify specific functions
      mockDependency = myDependencyProvider.$get();
      mockDependency.getSomething = function() { return 'mockReturnValue'; };
      $provide.value('myDependency', mockDependency);
  });

  it('should return value from mock dependency', inject(function (myService) {
      expect(myService.useDependency()).toBe('mockReturnValue');
  }));

});

컨트롤러가 다음과 같은 종속성을 갖도록 작성된 경우 :

app.controller("SomeController", ["$scope", "someDependency", function ($scope, someDependency) {
    someDependency.someFunction();
}]);

그런 다음 someDependencyJasmine 테스트에서 다음과 같이 가짜 만들 수 있습니다 .

describe("Some Controller", function () {

    beforeEach(module("app"));


    it("should call someMethod on someDependency", inject(function ($rootScope, $controller) {
        // make a fake SomeDependency object
        var someDependency = {
            someFunction: function () { }
        };

        spyOn(someDependency, "someFunction");

        // this instantiates SomeController, using the passed in object to resolve dependencies
        controller("SomeController", { $scope: scope, someDependency: someDependency });

        expect(someDependency.someFunction).toHaveBeenCalled();
    }));
});

나는 최근에 AngularJS에서 모의 ​​테스트를 더 쉽게 만들어 줄 ngImprovedTesting을 출시했습니다.

fooService 및 barService 종속성이 모의 된 'myService'( "myApp"모듈에서)를 테스트하려면 Jasmine 테스트에서 다음을 수행하면됩니다.

beforeEach(ModuleBuilder
    .forModule('myApp')
    .serviceWithMocksFor('myService', 'fooService', 'barService')
    .build());

ngImprovedTesting에 대한 자세한 내용은 소개 블로그 게시물을 확인하십시오. http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/


나는 이것이 오래된 질문이라는 것을 알고 있지만 다른 쉬운 방법이 있습니다. 모의를 만들고 하나의 기능에 주입 된 원본을 비활성화 할 수 있습니다. 모든 방법에서 spyOn을 사용하여 수행 할 수 있습니다. 아래 코드를 참조하십시오.

var mockInjectedProvider;

    beforeEach(function () {
        module('myModule');
    });

    beforeEach(inject(function (_injected_) { 
      mockInjectedProvider  = mock(_injected_);
    });

    beforeEach(inject(function (_base_) {
        baseProvider = _base_;
    }));

    it("injectedProvider should be mocked", function () {
    mockInjectedProvider.myFunc.andReturn('testvalue');    
    var resultFromMockedProvider = baseProvider.executeMyFuncFromInjected();
        expect(resultFromMockedProvider).toEqual('testvalue');
    }); 

    //mock all service methods
    function mock(angularServiceToMock) {

     for (var i = 0; i < Object.getOwnPropertyNames(angularServiceToMock).length; i++) {
      spyOn(angularServiceToMock,Object.getOwnPropertyNames(angularServiceToMock)[i]);
     }
                return angularServiceToMock;
    }

참고 URL : https://stackoverflow.com/questions/14773269/injecting-a-mock-into-an-angularjs-service

반응형

'IT' 카테고리의 다른 글

WSDL을 사용하는 방법  (0) 2020.07.24
sed : 일치하는 그룹 만 인쇄  (0) 2020.07.24
여러 줄 문자에 줄임표 적용  (0) 2020.07.24
대체에서 데이터 유형을 변경하는 방법  (0) 2020.07.24
ReactJS 호출 메소드  (0) 2020.07.24