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

     2023-02-26     241

关键词:

【中文标题】如何使用 Jasmine 监视值属性(而不是方法)【英文标题】:How to spyOn a value property (rather than a method) with Jasmine 【发布时间】:2014-01-19 17:25:57 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

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

所以要监视您使用的 getter/setter: const spy = spyOnProperty(myObj, 'myGetterName', 'get'); 其中 myObj 是您的实例,“myGetterName”是您的类中定义为 get myGetterName() 的实例的名称,第三个参数是 getset 的类型。

您可以使用与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 方法是here

使用 jasmine 2.6.1 回答原始问题,您将:

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

【讨论】:

如果valueAObservableSubject,我该怎么做?我收到Property valueA does not have access type get 这可能意味着您不能在该属性上使用它。 spyOnProperty 正在使用 getOwnPropertyDescriptor 并检查该属性描述符的访问类型 get|set 是否存在。您收到的错误是因为未设置属性描述符或未为您尝试监视的属性设置或获取。 Jasmine 这样做: const descriptor = Object.getOwnPropertyDescriptor ... if(!descriptor[accessType]) // 抛出错误 那么,如果没有明确的 getter 和 setter 方法,就没有办法窥探属性吗?间谍是使用的属性。 @Dominik 在这里,我在一篇较长的文章中写下了与此相关的所有幕后内容:medium.com/@juanlizarazo/… @Mathieu 这不是一个好的断言,因为它只是断言我们已经从我们告诉间谍要做的事情中知道的事情,但这正是他们所要求的以及他们相同的问题代码 sn-p ¯_(ツ)_/¯ 他们的问题的重点是如何监视财产,而不是他们的具体例子。【参考方案2】:

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

【讨论】:

using spyOn 明确表示我想模拟一些东西,而我直接设置属性隐含表示我想模拟一些东西,我不确定其他人会明白我在模拟一些东西时他正在阅读代码。另一种情况是我不想改变对象的内部行为,例如如果我改变数组的长度属性,数组会被修剪,所以模拟会更好 @Shuping,在这种情况下,您不会在嘲笑。你会存根,这完全没问题。您只会在测试中“改变行为”,这是您尝试使用 spyOn 实现的目标。 您可能想监视运行时对象原型以确保该属性将在运行时存在。如果属性不存在,则 Jasmine spyOn 未通过测试。 一个例子是设置或删除window.sessionStorage:TypeError: Cannot assign to read only property 'sessionStorage' of object '#<Window>' 在javascript中重新分配对象属性并不总是可以的【参考方案3】:

Jasmine 没有该功能,但您可以使用 Object.defineProperty 一起破解某些东西。

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

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

【讨论】:

【参考方案4】:

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

这里我设置了getclientWidthdiv.nativeElement 对象。

【讨论】:

【参考方案5】:

正确的做法是使用 spy on 属性,它可以让您模拟具有特定值的对象的属性。

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

【讨论】:

【参考方案6】:

如果您使用的是 ES6 (Babel) 或 TypeScript,您可以使用 get 和 set 访问器来存根属性

export class SomeClassStub 
  getValueA = jasmine.createSpy('getValueA');
  setValueA = jasmine.createSpy('setValueA');
  get valueA()  return this.getValueA(); 
  set valueA(value)  this.setValueA(value); 

然后在您的测试中,您可以检查该属性是否设置为:

stub.valueA = 'foo';

expect(stub.setValueA).toHaveBeenCalledWith('foo');

【讨论】:

或者,如果 getter 是被测类的一部分,则可以将存根注入子类中。【参考方案7】:

假设有这样的方法需要测试 小图的src属性需要检查

function reportABCEvent(cat, type, val) 
                var i1 = new Image(1, 1);
                var link = getABC('creosote');
                    link += "&category=" + String(cat);
                    link += "&event_type=" + String(type);
                    link += "&event_value=" + String(val);
                    i1.src = link;
                

下面的 spyOn() 会导致“新图像”被输入来自测试的假代码 spyOn 代码返回一个只有 src 属性的对象

由于变量“hook”的范围是在 SpyOn 中的假代码中可见,并且稍后在调用“reportABCEvent”之后也可见

describe("Alphabetic.ads", function() 
    it("ABC events create an image request", function() 
    var hook=;
    spyOn(window, 'Image').andCallFake( function(x,y) 
          hook= src:  
          return hook;
      
      );
      reportABCEvent('testa', 'testb', 'testc');
      expect(hook.src).
      toEqual('[zubzub]&arg1=testa&arg2=testb&event_value=testc');
    );

这适用于 jasmine 1.3,但如果“andCallFake”更改为,则可能适用于 2.0 2.0 名称

【讨论】:

【参考方案8】:

我正在使用剑道网格,因此无法将实现更改为 getter 方法,但我想围绕这个进行测试(模拟网格)而不是测试网格本身。我使用的是间谍对象,但这不支持属性模拟,所以我这样做:

    this.$scope.ticketsGrid =  
        showColumn: jasmine.createSpy('showColumn'),
        hideColumn: jasmine.createSpy('hideColumn'),
        select: jasmine.createSpy('select'),
        dataItem: jasmine.createSpy('dataItem'),
        _data: []
     

虽然有点啰嗦,但很管用

【讨论】:

【参考方案9】:

我知道我在这里聚会有点晚了,但是,

您可以直接访问调用对象,它可以为您提供每次调用的变量

expect(spy.calls.argsFor(0)[0].value).toBe(expectedValue)

【讨论】:

【参考方案10】:

您不能模拟变量,但可以为其创建 getter 函数并在您的规范文件中模拟该方法。

【讨论】:

如何将对不同变量/类属性的引用作为方法参数而不是值?

】如何将对不同变量/类属性的引用作为方法参数而不是值?【英文标题】:Howtoputareferencetodifferentvariables/classpropertiesasmethodparameterinsteadofavalue?【发布时间】:2022-01-2403:11:03【问题描述】:我需要使用逻辑创建多个editTexts来处理... 查看详情

使用 Jasmine 监视 Backbone.js 路由调用

】使用Jasmine监视Backbone.js路由调用【英文标题】:SpyingonBackbone.jsroutecallswithJasmine【发布时间】:2012-08-0413:10:37【问题描述】:在监视骨干路由器上的方法调用以确保它在给定路由上调用正确的方法时遇到问题。测试摘录describe\'R... 查看详情

如何对 DOM 操作进行单元测试(使用 jasmine)

】如何对DOM操作进行单元测试(使用jasmine)【英文标题】:howtounittestDOMmanipulation(withjasmine)【发布时间】:2013-04-1608:14:13【问题描述】:我需要用jasmine对一些DOM操作函数进行单元测试(目前我在浏览器和Karma中运行我的测试)我... 查看详情

使用 Jasmine 监视没有对象的函数

】使用Jasmine监视没有对象的函数【英文标题】:UsingJasminetospyonafunctionwithoutanobject【发布时间】:2012-03-1914:09:23【问题描述】:我是Jasmine的新手,刚刚开始使用它。我有一个库js文件,其中包含许多与任何对象(即全局)无关的... 查看详情

调试器如何只看到值而不是变量的内存地址

】调试器如何只看到值而不是变量的内存地址【英文标题】:Debuggerhowtoonlyseevaluesnotmemoryaddressesofvariables【发布时间】:2016-12-1911:37:22【问题描述】:最近我一直在VisualStudio中广泛使用结构和类。它们中的大多数都有很多值,这... 查看详情

使用 jasmine 和 karma 进行单元测试时形成数组错误

】使用jasmine和karma进行单元测试时形成数组错误【英文标题】:Formsarrayerrorwhileunittestusingjasmineandkarma【发布时间】:2021-01-1909:04:36【问题描述】:我正在为Angular应用程序版本9编写单元测试用例。但我遇到了错误。TypeError:无法读... 查看详情

如何在 Jasmine 1 中监视 Falcor 数据模型构造函数

】如何在Jasmine1中监视Falcor数据模型构造函数【英文标题】:HowtospyonaFalcorDataModelconstructorinJasmine1【发布时间】:2017-10-2216:58:34【问题描述】:我正在尝试模拟require(\'falcor\');返回的构造函数我有两条路线,一条使用vardataModel=newfa... 查看详情

如何使用jasmine使用dom元素测试javascript?

我试图在jasmine中为JavaScript代码编写测试,包括不起作用的DOM元素。当我只测试JavaScript代码(只是简单的函数而不是DOM元素)时,它可以工作。我一直在研究这个问题并且找不到答案。我也尝试使用jsdom,因为它应该在测试DOM元... 查看详情

如何在不使用 Angular 的 spyOn 的情况下检查服务中的方法是不是在 Jasmine 单元测试中被调用?

...在不使用Angular的spyOn的情况下检查服务中的方法是不是在Jasmine单元测试中被调用?【英文标题】:HowtocheckifamethodfromaserviceiscalledornotinJasmineunittestingwithoutusingspyOninAngular?如何在不使用Angular的spyOn的情况下检查服务中的方法是否在J... 查看详情

Qt:如何在 C++ 端而不是 QML 上监视 Q_PROPERTY 更改

】Qt:如何在C++端而不是QML上监视Q_PROPERTY更改【英文标题】:Qt:HowtomonitoraQ_PROPERTYchangeonC++sideinsteadofQML【发布时间】:2018-02-1517:28:18【问题描述】:我使用的是Qt5.9.3。我在我的应用程序的main.qml中声明了以下属性代码://main.qmlMyQ... 查看详情

如何使用 inotifywait 监视文件夹而不是文件夹中的文件

】如何使用inotifywait监视文件夹而不是文件夹中的文件【英文标题】:Howtouseinotifywaittowatchfileswithinfolderinsteadoffolder【发布时间】:2017-11-1014:29:42【问题描述】:我想使用inotifyway来监控文件夹中新创建或移动的文件但只监控文件... 查看详情

如何仅为方法而不是全局设置 TCPSocket 属性?

】如何仅为方法而不是全局设置TCPSocket属性?【英文标题】:HowdoIsetTCPSocketattributesforonlyamethodandnotglobally?【发布时间】:2017-01-0316:35:18【问题描述】:我正在使用带有Ruby2.3.0的Rails4.2.7。我有通过SOCKS代理获取网页的代码require"reso... 查看详情

如何覆盖属性的 JSON 序列化,将值序列化为字符串而不是对象?

】如何覆盖属性的JSON序列化,将值序列化为字符串而不是对象?【英文标题】:HowcanIoverridetheJSONserializationforaproperty,toserializethevalueasastringinsteadofanobject?【发布时间】:2021-03-0412:41:26【问题描述】:使用.Net4.8,我的所有实体框架... 查看详情

Jasmine 测试一个对象是不是有某种方法

】Jasmine测试一个对象是不是有某种方法【英文标题】:JasminetotestwhetheraobjecthasacertainmethodornotJasmine测试一个对象是否有某种方法【发布时间】:2013-03-1813:40:58【问题描述】:我正在使用Jasmine,我想测试一个对象是否有某种方法... 查看详情

.fadeOut() 方法使用可见性属性而不是显示属性

】.fadeOut()方法使用可见性属性而不是显示属性【英文标题】:The.fadeOut()methodtousevisibilitypropertyinsteadofdisplayproperty【发布时间】:2012-08-2316:13:20【问题描述】:.fadeOut()方法为匹配元素的不透明度设置动画。当opacity为0时,显示样... 查看详情

获取属性的名称而不是值

...evalue【发布时间】:2013-10-3114:04:52【问题描述】:我正在使用核心数据,并且一直在使用这样的代码:[self.formsetValue:self.comments.textforKey:@"comments"];我想将这样的代码放入一个循环中,我所有的核心数据名称都与属性名称相同。我... 查看详情

如何为 Jasmine 间谍的多个调用提供不同的返回值

】如何为Jasmine间谍的多个调用提供不同的返回值【英文标题】:HowtohavedifferentreturnvaluesformultiplecallsonaJasminespy【发布时间】:2015-01-0923:48:54【问题描述】:假设我在监视这样的方法:spyOn(util,"foo").andReturn(true);被测函数多次调用ut... 查看详情

在 Angular 中使用 Jasmine 使用 *ngIf 指令时,如何对元素是不是可见进行单元测试

】在Angular中使用Jasmine使用*ngIf指令时,如何对元素是不是可见进行单元测试【英文标题】:HowdoIunittestifanelementisvisiblewhenthe*ngIfdirectiveisusedusingJasmineinAngular在Angular中使用Jasmine使用*ngIf指令时,如何对元素是否可见进行单元测试【... 查看详情