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

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

spyOn(myObj, 'valueA').andReturn(1);
expect(myObj.valueA).toBe(1);
174578 次浏览

为什么不能直接在对象上改变它呢?Javascript 并不强制对象上的属性可见性。

Jasmine 没有这个功能,但是您可以使用 Object.defineProperty将一些东西拼凑在一起。

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

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

假设有一个类似的方法需要测试 小图像的 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 ()将导致“ new Image”从测试中获取假代码 SpyOn 代码返回一个只有 src 属性的对象

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

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版本的名称

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

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

虽然有点冗长,但还是很不错的

我知道我来晚了,但是,

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

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

如果您正在使用 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');

2017年2月,他们合并了一个添加了这个功能的公关,并于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 方法是 给你

回答最初的问题,用 Jasmine 2.6.1,你会:

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

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

这里我设置 div.nativeElement对象的 clientWidthget

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

正确的方法是使用属性监视,它将允许您模拟具有特定值的对象上的属性。

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

你也可以用 jasmin.creatSpyObj('ObjectName', [methodNames...], {prop1:propvalue, prop2:provalue2})