Jest中模拟IrohaTransactionExec的exec方法失效问题及解决
问题描述
我想用Jest模拟IrohaTransactionExec类的exec方法,让它返回预设的irohaResponse,但运行测试时,new IrohaTransactionExec().exec("testArg1","testArg2")执行了原方法,没返回预期结果,测试失败。相关代码和失败结果如下:
测试代码
it("mocking test", async () => { const irohaResponse = registered; const iroha = new IrohaTransactionExec() const mockfunc = jest.spyOn(iroha, "exec") mockfunc.mockReturnValue(Promise.resolve(irohaResponse)) expect(await new IrohaTransactionExec().exec("testArg1", "testArg2")).toEqual(irohaResponse) }, 10000)
IrohaTransactionExec类代码
import { IrohaClientBuilder, IrohaRequestParam } from "@post-pricing/library/lib/src/utility" import { IrohaInterface } from "@post-pricing/library/lib/src/const/irohaApi" export class IrohaTransactionExec { private irohaClient: IrohaClientBuilder private irohaRequestParam: IrohaRequestParam constructor() { this.irohaRequestParam = new IrohaRequestParam() } public async exec(shopCode: string, nptransactionId: string): Promise<IrohaInterface> { this.irohaClient = new IrohaClientBuilder() const client = await this.irohaClient.buildIrohaClient() const result = await client.searchTransactionAsync(this.irohaRequestParam.get(shopCode, nptransactionId)) return result[0].return } }
测试失败结果
expect(received).toEqual(expected) // deep equality - Expected - 37 + Received + 6 Object { "apiCommonResponseHeader": Object { "attributes": Object { "xsi:type": "ax22:ApiCommonResponseHeader", }, - "requestId": "12345", - "resultStatus": 0, + "errorCodeList": Array [ + "E0000007", + ], + "requestId": "PRC220909141357mwdix", + "resultStatus": 90, "serviceType": "01", - "shopCode": "akt0000001", + "shopCode": "testArg1"} } 20 | const mockfunc = jest.spyOn(iroha,"exec") 21 | mockfunc.mockReturnValue(Promise.resolve(irohaResponse)) > 22 | expect(await new IrohaTransactionExec().exec("testArg1","testArg2")).toEqual(irohaResponse) | ^ 23 | },10000) at Object.<anonymous> (test/functions/transactions/handler.spec.ts:22:82) ----------|---------|----------|---------|---------|------------------- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s ----------|---------|----------|---------|---------|------------------- All files | 0 | 0 | 0 | 0 | ----------|---------|----------|---------|---------|------------------- Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 3.754 s, estimated 4 s
问题原因
你用jest.spyOn只mock了单个实例的exec方法,但测试里又新建了一个IrohaTransactionExec实例——这个新实例完全不受之前的mock影响,所以调用的还是原方法。
正确实现方式
要mock整个类的exec方法,而不是单个实例,有两种常用方法:
方法一:mock类的原型方法(推荐)
直接修改类原型上的exec方法,这样所有新建的实例都会使用mock逻辑:
it("mocking test", async () => { const irohaResponse = registered; // mock整个类的原型上的exec方法,用mockResolvedValue简化异步处理 const mockExec = jest.spyOn(IrohaTransactionExec.prototype, "exec") .mockResolvedValue(irohaResponse); // 现在新建的实例调用exec会返回预设值 expect(await new IrohaTransactionExec().exec("testArg1", "testArg2")).toEqual(irohaResponse); // 测试后清理mock,避免影响其他测试用例 mockExec.mockRestore(); }, 10000)
方法二:mock整个类(彻底隔离)
如果需要完全替换类的实现,可以用jest.mock:
// 先导入目标类 import { IrohaTransactionExec } from '../path/to/IrohaTransactionExec'; // mock整个类的实现 jest.mock('../path/to/IrohaTransactionExec', () => { return { IrohaTransactionExec: jest.fn().mockImplementation(() => { return { exec: jest.fn().mockResolvedValue(registered) }; }) }; }); it("mocking test", async () => { expect(await new IrohaTransactionExec().exec("testArg1", "testArg2")).toEqual(registered); }, 10000)
注意事项
- 用
mockResolvedValue比mockReturnValue(Promise.resolve(...))更简洁,专门适配异步函数的mock场景。 - 测试完成后记得用
mockRestore()清理mock,防止污染其他测试用例。
内容的提问来源于stack exchange,提问作者Heisenberg
相关产品推荐
相关产品推荐

