Ron*_*ald 9 javascript jasmine
在我的 Angular 测试中模拟依赖项时,我通常使用jasmine.createSpyObj以下命令创建一个间谍对象:
const serviceSpy= jasmine.createSpyObj('MyService', ['method']);
Run Code Online (Sandbox Code Playgroud)
然后将其提供给 TestBed:
providers: [
{provide: MyService, useValue: serviceSpy}
]
Run Code Online (Sandbox Code Playgroud)
当我在测试中使用它时,我可以指定所需的返回值:
serviceSpy.method.and.returnValue(of([...]));
Run Code Online (Sandbox Code Playgroud)
现在我还需要模拟属性,但我不知道应该如何完成。createSpyObj确实允许定义属性名称:
const serviceSpy= jasmine.createSpyObj('MyService', ['method'], ['property']);
Run Code Online (Sandbox Code Playgroud)
但我已经尝试了基于大量文章和答案的各种解决方案,但没有任何成功,例如:
// Cannot read property 'and' of undefined
serviceSpy.property.and.returnValue(true);
// not declared configurable
spyOnProperty(serviceSpy, 'property').and.returnValue(true);
// no build errors, but value stays 'undefined'
serviceSpy.property = true;
Run Code Online (Sandbox Code Playgroud)
我可以让它“一半”工作的唯一方法是:
let fakeValue = true;
const serviceSpy= jasmine.createSpyObj('MyService', ['method'], {'property': fakeValue});
Run Code Online (Sandbox Code Playgroud)
这里的问题是它在创建时是一次性的。如果我想改变测试中的期望值,它不起作用。
fakeValue = false;
serviceSpy.property ==> stays to the initial value 'true';
Run Code Online (Sandbox Code Playgroud)
是否存在通过创建 spy 对象来解决模拟方法和属性的解决方案,或者我应该创建我自己的假类,然后在其上使用spyOnand spyOnProperty?
我还想知道createSpyObj定义中的属性数组的用法是什么。到目前为止,我还没有在网上看到任何解释它的例子。
jon*_*rpe 23
根据文档(强调我的):
您可以通过将一个数组或属性散列作为第三个参数传递给
createSpyObj. 在这种情况下,您将没有对创建的间谍的引用,因此如果您以后需要更改他们的间谍策略,则必须使用Object.getOwnPropertyDescriptor方法。Run Code Online (Sandbox Code Playgroud)it("creates a spy object with properties", function() { let obj = createSpyObj("myObject", {}, { x: 3, y: 4 }); expect(obj.x).toEqual(3); Object.getOwnPropertyDescriptor(obj, "x").get.and.returnValue(7); expect(obj.x).toEqual(7); });
Spied 属性是描述符(参见例如Object.definePropertyMDN),因此要访问 spy 对象,您需要获取描述符对象,然后与定义在其上的get和set方法进行交互。
在 TypeScript 中,编译器需要一点帮助。createSpyObj返回anyor SpyObj<T>,并且 aSpyObj仅将方法定义为被监视:
type SpyObj<T> = T & {
[K in keyof T]: T[K] extends Func ? T[K] & Spy<T[K]> : T[K];
// | if it's a | spy on it | otherwise leave
// | callable | | it alone
};
Run Code Online (Sandbox Code Playgroud)
因此,要访问.and的描述符的getter,你需要可选的链接(如Object.getOwnPropertyDescriptor可能返回undefined)和一个类型断言到Spy:
(Object.getOwnPropertyDescriptor(obj, "x")?.get as Spy<() => number>).and.returnValue(7);
Run Code Online (Sandbox Code Playgroud)
非常感谢@jonrsharpe!我刚刚添加了一个功能,所以我可以这样做:
spyPropertyGetter(spy, 'propName').and.returnValue(...)
Run Code Online (Sandbox Code Playgroud)
其中定义为:
spyPropertyGetter(spy, 'propName').and.returnValue(...)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9082 次 |
| 最近记录: |