同一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
相关产品推荐
相关产品推荐

