programing

각도 테스트 방법JS 커스텀 프로바이더

i4 2023. 4. 6. 20:45
반응형

각도 테스트 방법JS 커스텀 프로바이더

프로바이더 유닛 테스트의 예를 들어보신 분 계십니까?

예를 들어 다음과 같습니다.

config.discloss 。

angular.module('app.config', [])
  .provider('config', function () {
    var config = {
          mode: 'distributed',
          api:  'path/to/api'
        };

    this.mode = function (type) {
      if (type) {
        config.isDistributedInstance = type === config.mode;
        config.isLocalInstance = !config.isDistributedInstance;
        config.mode = type;
        return this;
      } else {
        return config.mode;
      }
    };

    this.$get = function () {
      return config;
    };
  }]);

app.module

angular.module('app', ['app.config'])
  .config(['configProvider', function (configProvider) {
    configProvider.mode('local');
  }]);

app.js를 테스트에서 사용하고 있으며 이미 설정되어 있는 것을 확인합니다.configProvider서비스로 테스트할 수 있습니다.설정 기능을 테스트하려면 어떻게 해야 하나요?아니면 전혀 필요없나요?

저는 같은 질문을 했고, 구글 그룹의 답변에서 유효한 해결책을 찾았을 뿐이고, 이는 바이올린 예제를 참조한 것입니다.

프로바이더 코드를 테스트하는 방법은 다음과 같습니다(바이들 예의 코드와 나에게 적합한 코드를 따릅니다).

describe('Test app.config provider', function () {

    var theConfigProvider;

    beforeEach(function () {
        // Initialize the service provider 
        // by injecting it to a fake module's config block
        var fakeModule = angular.module('test.app.config', function () {});
        fakeModule.config( function (configProvider) {
            theConfigProvider = configProvider;
        });
        // Initialize test.app injector
        module('app.config', 'test.app.config');

        // Kickstart the injectors previously registered 
        // with calls to angular.mock.module
        inject(function () {});
    });

    describe('with custom configuration', function () {
        it('tests the providers internal function', function () {
            // check sanity
            expect(theConfigProvider).not.toBeUndefined();
            // configure the provider
            theConfigProvider.mode('local');
            // test an instance of the provider for 
            // the custom configuration changes
            expect(theConfigProvider.$get().mode).toBe('local');
        });
    });

});

저는 @Mark Gemmill의 솔루션을 사용해 왔습니다만, 그 후 우연히 이 조금 덜 상세한 솔루션을 발견하게 되었습니다.그 결과 가짜 모듈을 사용할 필요가 없어졌습니다.

https://stackoverflow.com/a/15828369/1798234

그렇게,

var provider;

beforeEach(module('app.config', function(theConfigProvider) {
    provider = theConfigProvider;
}))

it('tests the providers internal function', inject(function() {
    provider.mode('local')
    expect(provider.$get().mode).toBe('local');
}));


프로바이더 $get 메서드에 의존관계가 있는 경우 수동으로 전달할 수 있습니다.

var provider;

beforeEach(module('app.config', function(theConfigProvider) {
    provider = theConfigProvider;
}))

it('tests the providers internal function', inject(function(dependency1, dependency2) {
    provider.mode('local')
    expect(provider.$get(dependency1, dependency2).mode).toBe('local');
}));


또는 $injector를 사용하여 새 인스턴스를 만듭니다.

var provider;

beforeEach(module('app.config', function(theConfigProvider) {
    provider = theConfigProvider;
}))

it('tests the providers internal function', inject(function($injector) {
    provider.mode('local')
    var service = $injector.invoke(provider);
    expect(service.mode).toBe('local');
}));


또, 상기의 어느쪽이든, 개개의 프로바이더를 재구성할 수 있습니다.it의 성명describeblock. 단, 복수의 테스트에 대해 프로바이더를 1회만 설정할 필요가 있는 경우는, 이것을 실행할 수 있습니다.

var service;

beforeEach(module('app.config', function(theConfigProvider) {
    var provider = theConfigProvider;
    provider.mode('local');
}))

beforeEach(inject(function(theConfig){
    service = theConfig;
}));

it('tests the providers internal function', function() {
    expect(service.mode).toBe('local');
});

it('tests something else on service', function() {
    ...
});

@Stephane Catala의 답변은 특히 도움이 되었고, 나는 내가 원하는 것을 얻기 위해 그의 provider Getter를 이용했다.프로바이더가 초기화를 실시하도록 한 후, 실제 서비스를 실시해, 다양한 설정으로 올바르게 동작하고 있는지를 검증하는 것이 중요합니다.코드 예:

    angular
        .module('test', [])
        .provider('info', info);

    function info() {
        var nfo = 'nothing';
        this.setInfo = function setInfo(s) { nfo = s; };
        this.$get = Info;

        function Info() {
            return { getInfo: function() {return nfo;} };
        }
    }

Jasmine 테스트 사양:

    describe("provider test", function() {

        var infoProvider, info;

        function providerGetter(moduleName, providerName) {
            var provider;
            module(moduleName, 
                         [providerName, function(Provider) { provider = Provider; }]);
            return function() { inject(); return provider; }; // inject calls the above
        }

        beforeEach(function() {
            infoProvider = providerGetter('test', 'infoProvider')();
        });

        it('should return nothing if not set', function() {
            inject(function(_info_) { info = _info_; });
            expect(info.getInfo()).toEqual('nothing');
        });

        it('should return the info that was set', function() {
            infoProvider.setInfo('something');
            inject(function(_info_) { info = _info_; });
            expect(info.getInfo()).toEqual('something');
        });

    });

다음으로 피칭 프로바이더를 적절히 캡슐화하는 작은 도우미를 나타냅니다.따라서 개별 테스트 간의 분리가 확보됩니다.

  /**
   * @description request a provider by name.
   *   IMPORTANT NOTE: 
   *   1) this function must be called before any calls to 'inject',
   *   because it itself calls 'module'.
   *   2) the returned function must be called after any calls to 'module',
   *   because it itself calls 'inject'.
   * @param {string} moduleName
   * @param {string} providerName
   * @returns {function} that returns the requested provider by calling 'inject'
   * usage examples:
    it('fetches a Provider in a "module" step and an "inject" step', 
        function() {
      // 'module' step, no calls to 'inject' before this
      var getProvider = 
        providerGetter('module.containing.provider', 'RequestedProvider');
      // 'inject' step, no calls to 'module' after this
      var requestedProvider = getProvider();
      // done!
      expect(requestedProvider.$get).toBeDefined();
    });
   * 
    it('also fetches a Provider in a single step', function() {
      var requestedProvider = 
        providerGetter('module.containing.provider', 'RequestedProvider')();

      expect(requestedProvider.$get).toBeDefined();
    });
   */
  function providerGetter(moduleName, providerName) {
    var provider;
    module(moduleName, 
           [providerName, function(Provider) { provider = Provider; }]);
    return function() { inject(); return provider; }; // inject calls the above
  }
  • 프로바이더를 취득하는 프로세스는 완전히 캡슐화되어 테스트 간의 분리를 줄이는 폐쇄 변수가 필요하지 않습니다.
  • 프로세스는 두 단계로 나눌 수 있습니다. 두 단계는 각각 유닛 테스트 내에서 '실행' 및 '실행'으로 분류할 수 있습니다.
  • 분할할 필요가 없는 경우, 프로바이더를 취득하는 것은, 1개의 커맨드로 간단하게 실시할 수 있습니다.

개인적으로 저는 이 기술을 외부 라이브러리에서 들어오는 공급자를 조롱하기 위해 사용합니다. 모든 테스트에 대해 도우미 파일에 넣을 수 있습니다.물론 이 질문에서와 같이 커스텀 프로바이더에서도 동작할 수 있습니다.앱이 프로바이더를 호출하기 전에 해당 모듈의 프로바이더를 재정의하는 것입니다.

describe('app', function() {
  beforeEach(module('app.config', function($provide) {
    $provide.provider('config', function() {
      var mode = jasmine.createSpy('config.mode');

      this.mode = mode;

      this.$get = function() {
        return {
          mode: mode
        };
      };
    });
  }));

  beforeEach(module('app'));

  describe('.config', function() {
    it('should call config.mode', inject(function(config) {
      expect(config.mode).toHaveBeenCalled();
    }));
  });
});

때했습니다.module().

또, 상기의 몇개의 솔루션을 시험해 본 결과, 프로바이더를 찾을 수 없었던 것도 몇개의 문제가 있었기 때문에, 대체의 어프로치의 필요성을 강조했습니다.

그 후 새로운 설정값의 사용을 반영하고 있는지 확인하기 위해 설정을 사용한 테스트를 추가했습니다.

describe("Service: My Service Provider", function () {
    var myService,
        DEFAULT_SETTING = 100,
        NEW_DEFAULT_SETTING = 500;

    beforeEach(function () {

        function configurationFn(myServiceProvider) {
            /* In this case, `myServiceProvider.defaultSetting` is an ES5 
             * property with only a getter. I have functions to explicitly 
             * set the property values.
             */
            expect(myServiceProvider.defaultSetting).to.equal(DEFAULT_SETTING);

            myServiceProvider.setDefaultSetting(NEW_DEFAULT_SETTING);

            expect(myServiceProvider.defaultSetting).to.equal(NEW_DEFAULT_SETTING);
        }

        module("app", [
            "app.MyServiceProvider",
            configurationFn
        ]);

        function injectionFn(_myService) {
            myService = _myService;
        }

        inject(["app.MyService", injectionFn]);
    });

    describe("#getMyDefaultSetting", function () {

        it("should test the new setting", function () {
            var result = myService.getMyDefaultSetting();

             expect(result).to.equal(NEW_DEFAULT_SETTING);
        });

    });

});

언급URL : https://stackoverflow.com/questions/14771810/how-to-test-angularjs-custom-provider

반응형