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

同一Jasmine测试用例中spyOn与createSpyObj联用失败原因咨询

问题原因与解决办法

不是spyOn和createSpyObj的组合用法不合法,问题出在你用spyOn(x, "test")替换了原方法的执行逻辑:

当你调用spyOn(x, "test")时,Jasmine会把x.test替换成一个默认不执行原方法代码的间谍函数。这时候再调用x.test(mockObj),只会记录调用信息,不会执行原test方法里obj.someFunction()+100的逻辑——自然会出现someFunction未被调用、返回值为undefined的错误。

之前两段逻辑单独运行正常的原因:

  • 第一段测试没有替换test方法,原逻辑完整执行,所以断言通过
  • 第二段测试只关心test方法的调用参数,间谍函数的参数跟踪功能不受影响,所以单独跑也没问题

解决办法

1. 拆分测试用例(推荐)

单元测试的最佳实践是一个测试用例只验证一个行为,把两个逻辑拆成独立的it块:

// 验证test方法的业务逻辑
it("test if someFunction is called and return value calculated correctly", () => {
  let x = new X();
  let mockObj = jasmine.createSpyObj(["someFunction"]);
  mockObj.someFunction.and.returnValue(2000);

  let returnValue = x.test(mockObj);

  expect(mockObj.someFunction).toHaveBeenCalled();
  expect(returnValue).toBe(2100);
});

// 验证test方法的参数类型
it("test if test method receives Object type parameter", () => {
  let x = new X();
  spyOn(x, "test");
  
  let mockObj = jasmine.createSpyObj(["someFunction"]);
  x.test(mockObj);

  expect(x.test.calls.allArgs()[0][0]).toBeInstanceOf(Object);
});

2. 在同一测试用例中保留原方法逻辑

如果一定要放在同一个it里,给spyOn加上.and.callThrough(),让间谍函数执行原方法的逻辑,同时保留调用跟踪功能:

it("test both logic in one case", () => {
  let x = new X();
  // 让spy执行原方法逻辑
  spyOn(x, "test").and.callThrough();

  let mockObj = jasmine.createSpyObj(["someFunction"]);
  mockObj.someFunction.and.returnValue(2000);

  let returnValue = x.test(mockObj);

  // 验证业务逻辑
  expect(mockObj.someFunction).toHaveBeenCalled();
  expect(returnValue).toBe(2100);

  // 验证参数类型
  expect(x.test.calls.allArgs()[0][0]).toBeInstanceOf(Object);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 06:42:24