You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Jasmine监视对象字段的赋值操作?

如何用Jasmine断言对象方法对字段的赋值操作?

问题背景

你想要测试testObj.testObjFunc方法是否会把testObj.testObjField字段赋值为"foo",测试对象和你尝试的代码如下:

测试对象:

const testObj = {
    testObjField: null,
    testObjFunc: function() { this.testObjField = "foo"; }
}

你尝试的测试代码:

//arrange
const testObj = {
  testObjField: null,
  testObjFunc: function () {
    this.testObjField = 'foo';
  }
};

const testObjTestObjFieldSpy = spyOnProperty(testObj, 'testObjField', 'set');

//act
testObj.testObjFunc();

//assert
expect(testObjTestObjFieldSpy).toHaveBeenCalledWith('foo');

运行后出现错误:

Error: : Property testObjField does not have access type set

错误原因

这个报错的核心是:testObjField是普通的数据属性,而不是带有setter的访问器属性。spyOnProperty的第三个参数'set'专门用于监视访问器属性的setter方法,普通字段没有这个访问器逻辑,所以Jasmine会报错提示找不到对应的set访问类型。

正确解决方案

这里提供两种常用的解决方式,你可以根据测试需求选择:

方案1:直接断言字段的最终值(推荐)

如果你的测试核心需求是验证方法执行后字段的结果是否正确,这是最简洁直接的方式——不需要监视赋值过程,直接检查最终状态:

describe('testObj.testObjFunc', () => {
  it('should set testObjField to "foo"', () => {
    // Arrange
    const testObj = {
      testObjField: null,
      testObjFunc: function () {
        this.testObjField = 'foo';
      }
    };

    // Act
    testObj.testObjFunc();

    // Assert
    expect(testObj.testObjField).toBe('foo');
  });
});

方案2:监视赋值动作(适用于需要跟踪赋值过程的场景)

如果你确实需要确认赋值动作的细节(比如赋值次数、传入的参数),可以把普通字段改成带setter的访问器属性,再用spyOnProperty监视:

describe('testObj.testObjFunc', () => {
  it('should trigger the testObjField setter with "foo"', () => {
    // Arrange: 将普通属性转为访问器属性
    let internalValue = null;
    const testObj = {
      get testObjField() { return internalValue; },
      set testObjField(val) { internalValue = val; },
      testObjFunc: function () {
        this.testObjField = 'foo';
      }
    };

    // 监视setter,同时保留原有的赋值逻辑(and.callThrough())
    const setterSpy = spyOnProperty(testObj, 'testObjField', 'set').and.callThrough();

    // Act
    testObj.testObjFunc();

    // Assert
    expect(setterSpy).toHaveBeenCalledWith('foo');
    expect(testObj.testObjField).toBe('foo'); // 同时验证最终值正确
  });
});

总结

  • 优先选择方案1,因为测试的核心是验证业务逻辑的结果,而不是内部的赋值动作;
  • 只有当你需要跟踪赋值的具体过程(比如统计调用次数、验证参数)时,才需要使用方案2的访问器属性+setter监视方式。

内容的提问来源于stack exchange,提问作者manymanymore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 16:45:29