如何使用 Jasmine 监视值属性(而不是方法)

IT技术 javascript unit-testing mocking jasmine
2021-03-06 21:19:58

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

spyOn(myObj, 'valueA').andReturn(1);
expect(myObj.valueA).toBe(1);
6个回答

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

所以要监视您使用的 getter/setter: const spy = spyOnProperty(myObj, 'myGetterName', 'get'); 其中 myObj 是您的实例,'myGetterName' 是您的类中定义的那个的名称,get myGetterName() {}第三个参数是类型getor 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

spyOnProperty 方法在这里

用 jasmine 2.6.1 回答最初的问题,你会:

const spy = spyOnProperty(myObj, 'valueA', 'get').andReturn(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();
@Mathieu 这不是一个好的断言,因为它只是断言了我们从我们告诉间谍要做的事情中已经知道的东西,但这正是他们在问的问题和他们非常相同的问题代码片段 ¯_(ツ)_/¯ 重点他们的问题之一是如何监视财产,而不是他们的具体例子。
2021-04-20 21:19:58
那么,如果没有明确的 getter 和 setter 方法,就没有办法监视属性吗?间谍是使用的属性。
2021-04-30 21:19:58
如果valueA是 aObservable或 ,我该怎么做Subject我越来越Property valueA does not have access type get
2021-05-02 21:19:58
@Dominik 在这里,我在一篇较长的文章中写了与此相关的所有幕后内容:medium.com/@juanlizarazo/...
2021-05-03 21:19:58
这可能意味着您不能在该属性上使用它。spyOnProperty 正在使用 getOwnPropertyDescriptor 并检查该属性描述符的访问类型 get|set 是否存在。您收到的错误是因为未为您尝试监视的属性设置或获取属性描述符。Jasmine 这样做: const descriptor = Object.getOwnPropertyDescriptor ... if(!descriptor[accessType]) { // 抛出错误 }
2021-05-12 21:19:58

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

usingspyOn明确表示我想要模拟某些东西,而我直接设置属性隐式表示我想要模拟某些东西,我不确定其他人会在他阅读代码时理解我在嘲笑某些东西。另一种情况是我不想改变对象的内部行为,例如,如果我改变数组的长度属性,数组会被修剪,所以模拟会更好
2021-04-25 21:19:58
一个例子是设置或删除 window.sessionStorage: TypeError: Cannot assign to read only property 'sessionStorage' of object '#<Window>'
2021-04-30 21:19:58
在 javascript 中重新分配对象属性并不总是可能的
2021-05-05 21:19:58
@Shuping,在这种情况下,你不会在嘲笑。你会存根,这是完全没问题的。您只会在测试中“改变行为”,这正是您试图通过spyOn.
2021-05-11 21:19:58
可能您想监视运行时对象原型以确保该属性在运行时存在。spyOn如果该属性不存在,Jasmine 将无法通过测试。
2021-05-11 21:19:58

Jasmine 没有该功能,但您可以使用Object.defineProperty.

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

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

最好的方法是使用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);

这里我设置了对象getclientWidthof div.nativeElement

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

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