source

앵귤러에 모의 주입JS 서비스

bestscript 2023. 3. 21. 22:16

앵귤러에 모의 주입JS 서비스

나는 Angular를 가지고 있다.JS서비스가 작성되어 유닛테스트를 하고 싶습니다.

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에 의해 만들어지는 서비스를 모두 중지하는 것으로 보입니다.

내 유닛 테스트를 위해 주입된 서비스를 어떻게 조롱할 수 있는지 아는 사람?

감사해요.

데이빗

다음을 사용하여 서비스에 Mock을 주입할 수 있습니다.$provide.

종속성이 getSomething이라는 메서드를 가진 다음 서비스가 있는 경우:

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

다음과 같이 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를 명시적으로 삽입할 필요는 없습니다.my Service 주입 중 후드 아래에서 발생합니다.여기서 mockDependency를 셋업할 때 스파이일 수도 있습니다.

그 멋진 비디오로 연결시켜준 충성스런 브라운에게 감사한다.

제가 보기에는 서비스 자체를 조롱할 필요는 없습니다.서비스의 기능을 조롱하기만 하면 됩니다.이렇게 하면 앱 전체에서처럼 실제 서비스를 각도로 주입할 수 있습니다.그런 다음 필요에 따라 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();
}]);

가짜를 수 someDependency이런 재스민 테스트에서요.

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

나는 최근 Angular에서 모의 테스트를 해야 하는 ngInvedTesting을 출시했다.JS는 훨씬 쉬워.

fooService 및 barService 종속성을 조롱하여 myApp 모듈에서 'myService'를 테스트하려면 Jasmine 테스트에서 다음을 수행합니다.

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

ng Improved Testing에 대한 자세한 내용은 소개 블로그 포스트를 참조하십시오.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