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

测试创建新实例的函数:如何Mock构造函数及验证实例入组?

关于Mock实例构造函数与实例存储验证的测试方案

嘿,我来帮你拆解这个测试相关的问题,结合实际场景给你讲清楚~

1. 如何Mock实例的构造函数?

假设我们有这样的业务代码:一个State类,还有一个saveStateToInstance函数负责创建它的实例并存入数组:

// app.js
class State {
  constructor(data) {
    this.data = data;
  }
}

function saveStateToInstance(data, stateArray) {
  const newState = new State(data);
  stateArray.push(newState);
}

以Jest为例,在test.js里Mock构造函数有两种常用方式:

方式一:Mock整个类模块

如果State是导出的模块,你可以直接Mock它,同时保留原函数的逻辑:

// test.js
const { saveStateToInstance } = require('./app');
const State = require('./app').State;

// Mock State类,保留原函数的真实实现
jest.mock('./app', () => ({
  saveStateToInstance: jest.requireActual('./app').saveStateToInstance,
  State: jest.fn()
}));

test('函数正确创建State实例并加入数组', () => {
  const testArray = [];
  const testData = { username: 'pyan' };

  saveStateToInstance(testData, testArray);

  // 验证构造函数被调用了一次,参数正确
  expect(State).toHaveBeenCalledTimes(1);
  expect(State).toHaveBeenCalledWith(testData);
  // 验证数组里确实存入了实例
  expect(testArray.length).toBe(1);
  expect(testArray[0]).toBeInstanceOf(State);
});

方式二:Mock构造函数的返回值

如果你需要控制Mock实例的内容(比如验证实例属性),可以让Mock的构造函数返回预设对象:

jest.mock('./app', () => {
  const mockInstance = { data: null };
  const mockState = jest.fn((data) => {
    mockInstance.data = data;
    return mockInstance;
  });
  return {
    saveStateToInstance: jest.requireActual('./app').saveStateToInstance,
    State: mockState
  };
});

test('存入数组的实例包含正确数据', () => {
  const testArray = [];
  const testData = { username: 'pyan' };

  saveStateToInstance(testData, testArray);

  // 直接断言实例的属性是否匹配
  expect(testArray[0].data).toEqual(testData);
});

2. 是否有必要Mock构造函数?

这完全取决于你的测试目标:

  • 如果是验证「函数的行为逻辑」:比如确认函数确实调用了State构造函数,并且把结果存入数组,这时候Mock很有必要——你不需要关心State内部的实现细节,只需要验证交互是否符合预期。
  • 如果是验证「最终结果的正确性」:比如要确保存入数组的实例确实包含正确的状态,这时候建议用真实的State类。因为Mock会隔离真实的构造逻辑,如果State的构造函数后续修改了(比如加了新的属性处理),Mock测试可能会通过,但真实代码已经出错了。

简单说:行为测试用Mock,状态测试用真实实例,按需选择就好。

3. 验证实例存入数组的更优方法

比起只检查数组长度或构造函数调用,直接验证实例的内容是更可靠的方式:

用真实类的情况

直接断言实例的属性是否匹配输入数据:

test('存入数组的实例状态正确', () => {
  const testArray = [];
  const testData = { username: 'pyan' };

  saveStateToInstance(testData, testArray);

  expect(testArray.length).toBe(1);
  expect(testArray[0]).toBeInstanceOf(State);
  // 核心:验证实例的具体属性
  expect(testArray[0].data).toEqual(testData);
});

用Mock的情况

确保Mock的实例包含预期属性,然后直接断言数组中的实例:
就像前面例子里的expect(testArray[0].data).toEqual(testData),这样比只验证构造函数调用更能确保最终结果符合预期。

另外,还可以用快照测试(比如Jest的toMatchSnapshot()),如果实例的结构比较固定,快照能快速验证实例是否符合预期:

test('实例结构符合快照', () => {
  const testArray = [];
  const testData = { username: 'pyan' };

  saveStateToInstance(testData, testArray);

  expect(testArray[0]).toMatchSnapshot();
});

总结下来,最优的测试方案是结合行为验证和状态验证:既确认构造函数被正确调用,又确认存入数组的实例状态符合预期,这样能同时覆盖逻辑正确性和结果正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:04:41