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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:01:26