jasmine.createSpyObj具有属性 [英] jasmine.createSpyObj with properties
问题描述
在Angular测试中模拟依赖项时,通常使用jasmine.createSpyObj
创建一个间谍对象:
When mocking dependencies in my Angular tests, I usually create a spy object using jasmine.createSpyObj
:
const serviceSpy= jasmine.createSpyObj('MyService', ['method']);
然后将其提供给TestBed:
then provide it to the TestBed:
providers: [
{provide: MyService, useValue: serviceSpy}
]
在测试中使用它时,可以指定所需的返回值:
When I use it in my test, I can then specify the desired return value:
serviceSpy.method.and.returnValue(of([...]));
现在,我还需要模拟属性,但是我无法找到应该如何做. createSpyObj
确实允许定义属性名称:
Now I also need to mock properties and I cannot find out how it should be done. createSpyObj
does allow the definition of property names:
const serviceSpy= jasmine.createSpyObj('MyService', ['method'], ['property']);
但是我已经根据大量文章尝试了各种解决方案,并且没有任何成功的答案,例如:
but I've tried varies solutions based on the numerous articles and answers out there without any success, e.g.:
// 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;
我可以使其半工"化的唯一方法是:
The only way I could make it 'half' work is:
let fakeValue = true;
const serviceSpy= jasmine.createSpyObj('MyService', ['method'], {'property': fakeValue});
这里的问题是它在创建时是一次性设置的.如果我想在测试中更改期望值,它将无法正常工作.
The problem here is that it's a one-time set at creation. If I want to change the expected value in the test, it does not work.
fakeValue = false;
serviceSpy.property ==> stays to the initial value 'true';
是否存在通过创建间谍对象同时解决模拟方法和属性的解决方案,还是应该创建自己的伪类,然后可以在其中使用spyOn
和spyOnProperty
?
Does there exist a solution to both mock methods and properties by creating a spy object, or should I create my own fake class on which I can then use spyOn
and spyOnProperty
?
我还想知道createSpyObj
定义中的属性数组的用途.到目前为止,我还没有在网络上看到任何可以解释它的示例.
I would also like to know what the usage is of the properties array in the createSpyObj
definition. So far I have not seen any example on the web that explains it.
推荐答案
每文档(强调我的):
您可以通过以下方法快速创建一个具有多个属性的间谍对象: 将属性的数组或哈希作为第三个参数传递给
createSpyObj
.在这种情况下,您将无法参考已创建的 间谍,因此如果您以后需要更改其间谍策略,则可以 必须使用Object.getOwnPropertyDescriptor
方法.
You can create a spy object with several properties on it quickly by passing an array or hash of properties as a third argument to
createSpyObj
. In this case you won’t have a reference to the created spies, so if you need to change their spy strategies later, you will have to use theObject.getOwnPropertyDescriptor
approach.
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);
});
间谍属性是描述符(请参见例如 Object.defineProperty
),因此,要访问间谍对象,您需要获取描述符对象,然后与在其上定义的get
和set
方法进行交互.
Spied properties are descriptors (see e.g. Object.defineProperty
on MDN), so to access the spy objects you need to get the descriptor object then interact with the get
and set
methods defined on it.
在TypeScript中,编译器需要一些帮助. createSpyObj
返回任一any
或SpyObj<T>
,而SpyObj
仅将方法定义为被监视:
In TypeScript, the compiler needs a bit of help. createSpyObj
returns either any
or SpyObj<T>
, and a SpyObj
only defines the methods as being spied on:
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
};
因此要访问描述符的getter上的.and
,您需要类型断言到
So to access .and
on the descriptor's getter, you'll need optional chaining (as Object.getOwnPropertyDescriptor
may return undefined
) and a type assertion to a Spy
:
(Object.getOwnPropertyDescriptor(obj, "x")?.get as Spy<() => number>).and.returnValue(7);
这篇关于jasmine.createSpyObj具有属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!