如何使用Jasmine窥探值属性(而不是方法)

Shu*_*ing 95 javascript unit-testing mocking jasmine

Jasmine spyOn是改变方法行为的好方法,但有没有办法改变对象的值属性(而不是方法)?代码可能如下所示:

spyOn(myObj, 'valueA').andReturn(1);
expect(myObj.valueA).toBe(1);
Run Code Online (Sandbox Code Playgroud)

Jua*_*uan 84

2017年2月,他们合并了一个PR添加此功能,他们于2017年4月发布.

所以要监视你使用的getter/setter: const spy = spyOnProperty(myObj, 'myGetterName', 'get'); myObj是你的实例,'myGetterName'是你的类中定义的名称,get myGetterName() {}第三个param是类型getset.

您可以使用已经与创建的间谍一起使用的相同断言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.
Run Code Online (Sandbox Code Playgroud)

这是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();
Run Code Online (Sandbox Code Playgroud)

  • 如果`valueA`是`Observable`或`Subject`,我该怎么做?我得到`属性valueA没有访问类型get` (5认同)
  • 这可能意味着您不能在该属性上使用它。spyOnProperty使用getOwnPropertyDescriptor并检查该属性描述符的访问类型get | set是否存在。您收到的错误是因为未设置属性描述符或获取了您要监视的属性。茉莉花这样做:const描述符= Object.getOwnPropertyDescriptor ... if(!descriptor [accessType]){//引发错误} (3认同)

Eri*_*ric 12

Jasmine没有这个功能,但是你可以使用它来共同破解Object.defineProperty.

您可以重构代码以使用getter函数,然后监视getter.

spyOn(myObj, 'getValueA').andReturn(1);
expect(myObj.getValueA()).toBe(1);
Run Code Online (Sandbox Code Playgroud)

  • 对于茉莉花2来说:`和.returnValue(1)` (3认同)

Pau*_*ris 10

有什么理由你不能直接在对象上更改它吗?它不像javascript强制对象的属性可见性.

  • 使用 `spyOn` 明确表示我想要模拟某些东西,而我直接设置属性隐式表示我想要模拟某些东西,我不确定其他人会在他阅读代码时理解我在嘲笑某些东西。另一种情况是我不想改变对象的内部行为,例如如果我改变数组的长度属性,数组被修剪,所以模拟会更好 (3认同)
  • 一个例子是设置或删除window.sessionStorage:`TypeError:无法分配给对象'#<Window>'的只读属性'sessionStorage' (2认同)
  • 并非总是可以在javascript中重新分配对象属性 (2认同)

ale*_*oem 7

正确的方法是使用 spy on 属性,它允许您模拟具有特定值的对象上的属性。

const spy = spyOnProperty(myObj, 'valueA').and.returnValue(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();
Run Code Online (Sandbox Code Playgroud)


Mar*_*tin 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); }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的测试中,您可以检查该属性是否设置为:

stub.valueA = 'foo';

expect(stub.setValueA).toHaveBeenCalledWith('foo');
Run Code Online (Sandbox Code Playgroud)


Ani*_*Das 6

最好的方法是使用spyOnProperty。它需要3个参数,您需要通过getset作为第三个参数。

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);
Run Code Online (Sandbox Code Playgroud)

在这里,我设置getclientWidthdiv.nativeElement对象。