jasmine.createSpyObj具有属性 [英] jasmine.createSpyObj with properties

查看:99
本文介绍了jasmine.createSpyObj具有属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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';

是否存在通过创建间谍对象同时解决模拟方法和属性的解决方案,还是应该创建自己的伪类,然后可以在其中使用spyOnspyOnProperty?

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 the Object.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 ),因此,要访问间谍对象,您需要获取描述符对象,然后与在其上定义的getset方法进行交互.

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 返回任一anySpyObj<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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆