如何使用Jasmine窥探值属性(而不是方法)

时间:2014-01-02 09:38:20

标签: javascript unit-testing mocking jasmine

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

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

10 个答案:

答案 0 :(得分:64)

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

使用jasmine 2.6.1回答原始问题,你会:

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

答案 1 :(得分:10)

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

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

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

答案 2 :(得分:9)

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

答案 3 :(得分:3)

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

答案 4 :(得分:3)

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

我在这里设置get clientWidth div.nativeElementimport * as firebase from 'firebase/app'; import 'firebase/storage'; 。{/ p>

答案 5 :(得分: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()会导致“新图像”从测试中提供伪代码 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名称

答案 6 :(得分:1)

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

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

它有点长啰嗦,但它有效吗

答案 7 :(得分:0)

我知道这里的派对有点晚了,但是,

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

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

答案 8 :(得分:0)

正确的方法是对属性进行监视,它将使您可以模拟具有特定值的对象的属性。

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

答案 9 :(得分:-2)

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