종속성이있는 AngularJS 팩토리 단위 테스트


79

Angular 팩토리 (Karma + Jasmine 사용)를 단위 테스트 할 때 테스트중인 팩토리에 스텁 종속성을 어떻게 삽입합니까?

내 공장은 다음과 같습니다.

mod = angular.module('myFactoryMod', []);

mod.factory('myFactory', [
  '$log', 'oneOfMyOtherServices', function($log, svc) {
    return makeSomethingThatDoesSomethingWithTheseDependencies($log, svc);
  }
]);

oneOfMyOtherServices 내 공장을 인스턴스화 할 때 필요합니다.

내 테스트는 다음과 같습니다.

it('can get an instance of my factory', function() {
  var oneOfMyOtherServicesStub;

  angular.mock.module('myFactoryMod');

  oneOfMyOtherServicesStub = {
    someVariable: 1
  };

  //****How do I get my stub in my target? ****

  angular.mock.inject(['myFactory', function(target) {

      expect(target).toBeDefined();

    }
  ]);
})

NB 나는 $controller이것이 컨트롤러에 대해 허용 한다는 것을 알고 있지만 공장에 대해서는 동등한 것을 보지 못합니다.

답변:


93

내가 알고있는 이와 같은 작업을 수행하는 방법에는 두 가지가 있습니다.

  1. $provide모의를 주입 하려면 및 익명 모듈을 사용하십시오 .
  2. 조롱하려는 서비스를 삽입하고 재스민의 스파이 기능을 사용하여 모의 가치를 제공합니다.

두 번째 옵션은 테스트중인 코드가 주입 된 서비스에서 호출 할 메서드를 정확히 알고있는 경우에만 작동하며 쉽게 모의 처리 할 수 ​​있습니다. 방법이 아닌 서비스의 데이터 속성에 액세스하는 것처럼 보이므로 첫 번째 옵션을 추구하는 것이 가장 좋습니다.

사용 $provide은 대략 다음과 같습니다.

describe('myFactory', function () {
  // Load your module.
  beforeEach(module('myFactoryMod'));

  // Setup the mock service in an anonymous module.
  beforeEach(module(function ($provide) {
    $provide.value('oneOfMyOtherServicesStub', {
        someVariable: 1
    });
  }));

  it('can get an instance of my factory', inject(function(myFactory) {
    expect(myFactory).toBeDefined();
  }));
});

네, 선택 1이 갈 길이라고 생각합니다. 감사!
Roy Truelove

7
모든 테스트에 myFactory를 주입하고 싶습니다. beforeEach에서 할 수 있습니까? 시도했지만 작동하지 않았습니다 ...
Bennett McElwee 2013-09-20

10
이 답변 +1에 감사드립니다. 완전성을 위해 옵션 # 2에도 코드 예제를 추가하는 것이 좋습니다.
klode dec.

2
@BennettMcElwee 예, 할 수 있습니다. 이렇게 : var theFactory; beforeEach(inject(function(myFactory) { theFactory = myFactory; } )));그런 다음 theFactory테스트에 사용 하십시오.
bentsai 2014 년

1
Jasmine과 karma를 사용하여이 팩토리 메소드 getItemList를 어떻게 테스트 할 수 있습니까? 오류가 발생합니다 : [$ injector : unpr] errors.angularjs (function () {angular.module ( 'riskCanvasApp'). factory ( 'itemsService', itemsService); itemsService. $ inject = [ '$ http', '$ q ','$ compile ','UrlService ','accountDetailsMainService ','sharedService ','authenticationSvc ']; function itemsService ($ http, $ q, $ compile, urlService, accountDetailsMainService, sharedService, authenticationSvc) {
AMRESH PANDEY

12

@bentsai의 의견은 실제로 서비스 테스트에 매우 유용합니다. 완전성을 위해 나는 예를 추가하고 있습니다.

여기에 jasmine당신이 찾고있는 것을 대략적으로 수행 하는 테스트 가 있습니다. 참고 : 이것은 당신이 한 데 필요한 angular-mocks포함 (이 같은 기능을 제공 무엇 moduleinject).

describe('app: myApp', function() {
  beforeEach(module('myApp'));
  var $controller;
  beforeEach(inject(function(_$controller_) {
    $controller = _$controller_;
  }));
  // Factory of interest is called MyFactory
  describe('factory: MyFactory', function() {
    var factory = null;
    beforeEach(inject(function(MyFactory) {
      factory = MyFactory;
    }))
    it('Should define methods', function() {
      expect(factory.beAwesome).toBeDefined()
      expect(factory.beAwesome).toEqual(jasmine.any(Function))
    });
  });
});

이것은 모듈 및 관련 팩토리 정의가 어떻게 생겼는지에 대한 스텁입니다.

var app = angular.module('myApp', []);
app.factory('MyFactory', function() {
  var factory = {};
  factory.beAwesome = function() {
    return 'Awesome!';
  }
  return factory;
});

이 경우 inject()일반 각도 애플리케이션에서 예상하는 것처럼 종속성을 가져올 수 있음 이 분명 합니다. 따라서 이에 의존하는 테스트를 지원하기위한 요구 사항을 구축 할 수 있습니다.


2
테스트에서 MyFactory에 스텁 종속성을 삽입하는 부분을 놓쳤습니다.
skolsuper

두 번째 종속성은 어디에 있습니까?
Choco
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.