program tip

jasmine으로 단위 테스트를 할 때 AngularJS에서 서비스를 어떻게 모의합니까?

radiobox 2020. 11. 18. 08:52
반응형

jasmine으로 단위 테스트를 할 때 AngularJS에서 서비스를 어떻게 모의합니까?


이 전 서비스 있다고 가정 해 봅시다 shop두 상태 기반 서비스에 따라 달라집니다 schedulewarehouse. 단위 테스트 위해 다른 버전의 schedulewarehose어떻게 삽입 shop합니까?

내 서비스는 다음과 같습니다.

angular.module('myModule').service('shop', function(schedule, warehouse) {
    return {
        canSellSweets : function(numRequiredSweets){
             return schedule.isShopOpen()
                 && (warehouse.numAvailableSweets() > numRequiredSweets);
        }
    }
});

다음은 내 모의입니다.

var mockSchedule = {
    isShopOpen : function() {return true}
}
var mockWarehouse = {
    numAvailableSweets: function(){return 10};
}

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

expect(shop.canSellSweets(5)).toBe(true);
expect(shop.canSellSweets(20)).toBe(false);

beforeEach(function () {
  module(function ($provide) {
    $provide.value('schedule', mockSchedule);
  });
});

모듈은 angular-mocks 모듈에서 제공하는 기능입니다. 문자열 인수를 전달하면 해당 이름의 모듈이로드되고 모든 공급자, 컨트롤러, 서비스 등을 사양에 사용할 수 있습니다. 일반적으로 주입 기능을 사용하여로드됩니다. 콜백 함수를 전달하면 Angular의 $ injector 서비스를 사용하여 호출됩니다. 그런 다음이 서비스는 콜백 함수에 전달 된 인수를 확인하고 콜백에 전달해야하는 종속성을 추론합니다.


Atilla의 답변을 개선하고 KevSheedy의 의견에 대한 직접적인 답변으로 module('myApplicationModule')다음을 수행합니다.

beforeEach(module('myApplicationModule', function ($provide) {
  $provide.value('schedule', mockSchedule);
}));

CoffeeScript를 사용하면 몇 가지 문제가 발생하므로 끝에 null사용 합니다.

beforeEach ->
  module ($provide) ->
    $provide.value 'someService',
      mockyStuff:
        value : 'AWESOME'
    null

자세한 정보는 여기에서 확인할 수 있습니다.

https://docs.angularjs.org/guide/services#unit-testing

$ provide 서비스를 사용하려고합니다. 귀하의 경우

$provide.value('schedule', mockSchedule);

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

귀하의 예에서는 Jasmine 테스트에서만 교체해야합니다 ...

beforeEach(module('myModule'));

...와 함께 ...

beforeEach(ModuleBuilder.forModule('myModule').serviceWithMocks('shop').build());

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


다음과 같이 모듈에 모의 객체를 넣는 것이 더 간단합니다.

    beforeEach(function () {
    module('myApp');
    module({
      schedule: mockSchedule,
      warehouse: mockWarehouse
     }
    });
  });

you can use injection to get reference to these mocks for pre test manipulations :

var mockSchedule;
var mockWarehouse;

beforeEach(inject(function (_schedule_, _warehouse_) {
     mockSchedule = _schedule_;
     mockWarehouse = _warehouse_;
}));

I hope my answer is not that useless, but you can mock services by $provide.service

beforeEach(() => {
    angular.mock.module(
      'yourModule',
      ($provide) => {
        $provide.service('yourService', function() {
          return something;
        });
      }
    );
  });

As you are using jasmine, there is an alternative way to mock the calls with jasmine's spies (https://jasmine.github.io/2.0/introduction.html#section-Spies).

Using these you can be targeted with your function calls, and allow call throughs to the original object if required. It avoids clogging up the top of your test file with $provide and mock implementations.

In the beforeEach of your test I would have something like:

var mySchedule, myWarehouse;

beforeEach(inject(function(schedule, warehouse) {

  mySchedule = schedule;
  myWarehouse = warehouse;

  spyOn(mySchedule, 'isShopOpen').and.callFake(function() {
    return true;
  });

  spyOn(myWarehouse, 'numAvailableSweets').and.callFake(function() {
    return 10;
  });

}));

and this should work in similar fashion to the $provide mechanism, noting you have to provide local instances of the injected variables to spy on.

참고URL : https://stackoverflow.com/questions/19274274/how-do-you-mock-a-service-in-angularjs-when-unit-testing-with-jasmine

반응형