jasmine.createSpyObj 与属性

jasmine.createSpyObj with properties(jasmine.createSpyObj 与属性)
本文介绍了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';

是否存在通过创建 spy 对象来模拟方法和属性的解决方案,或者我应该创建自己的假类,然后我可以在其上使用 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.

推荐答案

根据 文档 (强调我的):

Per the documentation (emphasis mine):

您可以通过以下方式快速创建一个具有多个属性的间谍对象将属性数组或散列作为第三个参数传递给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 on MDN),因此要访问间谍对象,您需要获取描述符对象,然后与 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,而 SpyObj 仅将 methods 定义为被监视上:

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,您需要 可选链接(因为 Object.getOwnPropertyDescriptor 可能返回 undefined)和一个 类型断言到 Spy:

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 与属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

What#39;s a good way to reuse test code using Jasmine?(使用 Jasmine 重用测试代码的好方法是什么?)
Does Jasmine#39;s toThrow matcher require the argument to be wrapped in an anonymous function?(Jasmine 的 toThrow 匹配器是否需要将参数包装在匿名函数中?)
Jasmine - Spying on a method call within a constructor(Jasmine - 在构造函数中监视方法调用)
Getting requirejs to work with Jasmine(让 requirejs 与 Jasmine 一起工作)
How can I spy on a getter property using jasmine?(如何使用 jasmine 监视 getter 属性?)
Protractor Angular 2 Failed: unknown error: angular is not defined(Protractor Angular 2 失败:未知错误:未定义角度)