Jasmine으로 값 속성 (메서드가 아닌)을 감시하는 방법


115

Jasmine spyOn은 메서드의 동작을 변경하는 데 좋지만 객체의 값 속성 (메서드가 아닌)을 변경할 수있는 방법이 있습니까? 코드는 다음과 같을 수 있습니다.

spyOn(myObj, 'valueA').andReturn(1);
expect(myObj.valueA).toBe(1);

답변:


97

2017 년 2 월에이 기능을 추가 한 PR을 병합하여 2017 년 4 월에 출시했습니다.

따라서 getter / setter를 감시하려면 다음을 사용하십시오. const spy = spyOnProperty(myObj, 'myGetterName', 'get'); 여기서 myObj는 인스턴스이고 'myGetterName'은 클래스에 정의 된 이름이고 get myGetterName() {}세 번째 매개 변수는 get또는 set.

로 만든 스파이에 이미 사용하는 것과 동일한 어설 션을 사용할 수 있습니다 spyOn.

예를 들어 다음과 같이 할 수 있습니다.

const spy = spyOnProperty(myObj, 'myGetterName', 'get'); // to stub and return nothing. Just spy and stub.
const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.returnValue(1); // to stub and return 1 or any value as needed.
const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.callThrough(); // Call the real thing.

다음은 관심이있는 경우이 메서드를 사용할 수있는 github 소스 코드의 줄입니다.

https://github.com/jasmine/jasmine/blob/7f8f2b5e7a7af70d7f6b629331eb6fe0a7cb9279/src/core/requireInterface.js#L199

jasmine 2.6.1을 사용하여 원래 질문에 답하면 다음과 같이됩니다.

const spy = spyOnProperty(myObj, 'valueA', 'get').andReturn(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();

7
경우 어떻게 이렇게 할 valueAA는 Observable나 Subject? 나는군요Property valueA does not have access type get
— 카 목동

4
그것은 아마도 당신이 그 속성에서 그것을 사용할 수 없다는 것을 의미합니다. spyOnProperty는 getOwnPropertyDescriptor를 사용하고 해당 속성 설명자에 대한 액세스 유형 get | set이 존재하는지 확인합니다. 발생한 오류는 속성 설명자가 설정되지 않았거나 스파이하려는 속성에 대해 가져 오기 때문입니다. Jasmine은 다음을 수행합니다. const descriptor = Object.getOwnPropertyDescriptor ... if (! descriptor [accessType]) {// 오류 발생}
— Juan

그렇다면 명시적인 getter 및 setter 메서드없이 속성을 감시 할 방법이 없습니까? 스파이는 사용되는 속성입니다.
— Dominik

@Dominik 여기에 더 긴 기사에서 이것과 관련된 모든 내부 내용을 썼습니다. medium.com/@juanlizarazo/…
— Juan

1
@Mathieu 그것은 우리가 스파이에게 말한 것에서 우리가 이미 알고있는 것을 주장하기 때문에 좋은 주장이 아닙니다. 그들의 질문은 그들의 구체적인 예가 아니라 재산을 감시하는 방법이었습니다.
— Juan

12

개체에서 직접 변경할 수없는 이유는 무엇입니까? 자바 스크립트가 객체에 대한 속성의 가시성을 강제하는 것과는 다릅니다.


1
spyOn명시 적으로 사용 은 내가 무언가를 모의하고 싶다는 것을 나타내는 반면, 속성을 직접 설정하면 내가 무언가를 모의하고 싶다는 것을 암시 적으로 나타내며, 그가 코드를 읽을 때 내가 무언가를 조롱하고 있다는 것을 다른 사람이 이해할 수 있을지 확신 할 수 없습니다. 다른 경우는 객체의 내부 동작을 변경하지 않으려는 것입니다. 예를 들어 배열의 길이 속성을 변경하면 배열이 잘
— 리므로

@Shuping,이 경우에는 조롱하지 않을 것입니다. 당신은 완벽하게 괜찮은 스터 빙을 할 것입니다. 당신은 당신이 spyOn.
— Fabio Milheiro

런타임에 속성이 존재하는지 확인하기 위해 런타임 개체 프로토 타입을 감시하려고 할 수 있습니다. Jasmine spyOn은 속성이 존재하지 않으면 테스트에 실패합니다.
— sennett

2
한 예로 설정하거나 삭제 window.sessionStorage하는 것입니다 :TypeError: Cannot assign to read only property 'sessionStorage' of object '#<Window>'
— 크리스 Sattinger

2
자바 스크립트 객체 속성을 재 할당하는 것이 항상 가능한 것은 아니다
— 르노

12

Jasmine에는 이러한 기능이 없지만 .NET을 사용하여 함께 해킹 할 수 있습니다 Object.defineProperty.

getter 함수를 사용하도록 코드를 리팩터링 한 다음 getter를 감시 할 수 있습니다.

spyOn(myObj, 'getValueA').andReturn(1);
expect(myObj.getValueA()).toBe(1);

예, 그게 제가 지금 할 수있는 일입니다.
— 년

4
자스민이 것이있다 :and.returnValue(1)
— jtzero

9

가장 좋은 방법은 spyOnProperty. 3 개의 매개 변수가 필요 하며 세 번째 매개 변수로 전달 get하거나 전달해야합니다 set.

예

const div = fixture.debugElement.query(By.css('.ellipsis-overflow'));
// now mock properties
spyOnProperty(div.nativeElement, 'clientWidth', 'get').and.returnValue(1400);
spyOnProperty(div.nativeElement, 'scrollWidth', 'get').and.returnValue(2400);

여기에 내가 설정하고 get의 clientWidth의 div.nativeElement객체를.


6

ES6 (Babel) 또는 TypeScript를 사용하는 경우 get 및 set 접근자를 사용하여 속성을 스텁 아웃 할 수 있습니다.

export class SomeClassStub {
  getValueA = jasmine.createSpy('getValueA');
  setValueA = jasmine.createSpy('setValueA');
  get valueA() { return this.getValueA(); }
  set valueA(value) { this.setValueA(value); }
}

그런 다음 테스트에서 속성이 다음으로 설정되었는지 확인할 수 있습니다.

stub.valueA = 'foo';

expect(stub.setValueA).toHaveBeenCalledWith('foo');

또는 getter가 테스트중인 클래스의 일부인 경우 스텁을 하위 클래스에 삽입 할 수 있습니다.
— ccprog

6

이 작업을 수행하는 올바른 방법은 속성에 대한 스파이를 사용하는 것입니다. 그러면 특정 값을 가진 개체의 속성을 시뮬레이션 할 수 있습니다.

const spy = spyOnProperty(myObj, 'valueA').and.returnValue(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();

1

테스트가 필요한 이와 같은 방법이 있다고 가정 src합니다. 작은 이미지 의 속성을 확인해야합니다.

function reportABCEvent(cat, type, val) {
                var i1 = new Image(1, 1);
                var link = getABC('creosote');
                    link += "&category=" + String(cat);
                    link += "&event_type=" + String(type);
                    link += "&event_value=" + String(val);
                    i1.src = link;
                }

아래의 spyOn ()은 "new Image"에 테스트의 가짜 코드를 제공하도록합니다. spyOn 코드는 src 속성 만있는 객체를 반환합니다.

변수 "hook"은 SpyOn의 가짜 코드에서 볼 수 있도록 범위가 지정되며 나중에 "reportABCEvent"가 호출 된 후에도

describe("Alphabetic.ads", function() {
    it("ABC events create an image request", function() {
    var hook={};
    spyOn(window, 'Image').andCallFake( function(x,y) {
          hook={ src: {} }
          return hook;
      }
      );
      reportABCEvent('testa', 'testb', 'testc');
      expect(hook.src).
      toEqual('[zubzub]&arg1=testa&arg2=testb&event_value=testc');
    });

이것은 jasmine 1.3 용이지만 "andCallFake"가 2.0 이름으로 변경되면 2.0에서 작동 할 수 있습니다.


1

나는 검도 그리드를 사용하고 있으므로 구현을 getter 메서드로 변경할 수 없지만이 주위를 테스트하고 (그리드 조롱) 그리드 자체를 테스트하지 않으려 고합니다. 스파이 개체를 사용하고 있었지만 속성 조롱을 지원하지 않으므로 이렇게합니다.

    this.$scope.ticketsGrid = { 
        showColumn: jasmine.createSpy('showColumn'),
        hideColumn: jasmine.createSpy('hideColumn'),
        select: jasmine.createSpy('select'),
        dataItem: jasmine.createSpy('dataItem'),
        _data: []
    } 

약간 긴 바람이지만 치료 효과가 있습니다.


0

여기 파티에 좀 늦었어요. 알지만

각 호출에 대한 변수를 제공 할 수있는 calls 객체에 직접 액세스 할 수 있습니다.

expect(spy.calls.argsFor(0)[0].value).toBe(expectedValue)

-3

변수를 모의 할 수는 없지만 이에 대한 getter 함수를 만들고 사양 파일에서 해당 메서드를 모의 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.