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는 ObservableSubject? 나는군요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);

여기에 내가 설정하고 getclientWidthdiv.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.