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

如何在Jest中重置方法的mockImplementation并重新指定返回值

解决Jest中Mock方法在不同测试用例设置不同返回值的问题

问题场景

已为TestService实现Mock,第一个测试用例因checkIfExistsInDB返回false执行成功,但第二个测试用例需要将该Mock方法改为返回true,尝试两种方法均无效:

初始Mock代码

jest.mock('../../lib/testService', () => ({
  TestService : jest.fn(() => ({
      callAPIProd: jest.fn().mockImplementation(() => Promise.resolve([{ DateTime: '2022-01-01'}])),
      getAuthToken: jest.fn().mockImplementation(() => Promise.resolve({ data: 'mock token' })),
      checkIfExistsInDB: jest.fn().mockImplementation(() => Promise.resolve(false)),
  })),
}));

测试用例代码

describe('getRates', () => {
    it('should insert rates into DB if not already available', async () => {
      const req = {} as Request;
      const res = { send: jest.fn() } as unknown as Response;

      await integration.getRates(req, res);

      expect(res.send).toHaveBeenCalledWith('New Rates Received');
    });

    it('should send response if rates are already available in DB', async () => {
      const req = {} as Request;
      const res = { send: jest.fn() } as unknown as Response;

      // 尝试过的两种无效方法
      // #1 重新调用jest.mock,无效
      // jest.mock(...)
      // #2 修改prototype,无效
      // TestService.prototype.checkIfExistsInDB = jest.fn().mockResolvedValue(true)

      await integration.getRates(req, res);

      expect(res.send).toHaveBeenCalledWith('Rates already available in DB');
    });
});

无效原因分析

  1. 测试用例内调用jest.mock无效:jest.mock会被Jest自动提升到模块顶部执行,测试用例内部的jest.mock无法覆盖模块级的Mock配置。
  2. 修改prototype无效:TestService是一个返回普通对象的工厂函数(jest.fn()),并非类,不存在prototype属性,修改它不会影响Mock实例的方法。

正确解决方案

步骤1:获取Mock实例的方法引用

在模块顶部导入TestService后,直接获取Mock工厂函数返回的实例引用:

import { TestService } from '../../lib/testService';
import integration from './your-integration-module'; // 替换为实际路径
import type { Request, Response } from 'express';

jest.mock('../../lib/testService', () => ({
  TestService : jest.fn(() => ({
      callAPIProd: jest.fn().mockResolvedValue([{ DateTime: '2022-01-01'}]),
      getAuthToken: jest.fn().mockResolvedValue({ data: 'mock token' }),
      checkIfExistsInDB: jest.fn().mockResolvedValue(false),
  })),
}));

// 获取TestService Mock返回的实例对象
const mockTestService = TestService.mock.results[0].value;

步骤2:在测试用例中重置并修改Mock返回值

在第二个测试用例中,直接重置目标Mock方法并设置新的返回值:

describe('getRates', () => {
    // 可选:每次测试前重置所有Mock,避免用例间污染
    beforeEach(() => {
        jest.clearAllMocks();
        // 重置为默认返回值
        mockTestService.checkIfExistsInDB.mockResolvedValue(false);
    });

    it('should insert rates into DB if not already available', async () => {
      const req = {} as Request;
      const res = { send: jest.fn() } as unknown as Response;

      await integration.getRates(req, res);

      expect(res.send).toHaveBeenCalledWith('New Rates Received');
    });

    it('should send response if rates are already available in DB', async () => {
      const req = {} as Request;
      const res = { send: jest.fn() } as unknown as Response;

      // 修改checkIfExistsInDB的返回值为true
      mockTestService.checkIfExistsInDB.mockResolvedValue(true);

      await integration.getRates(req, res);

      expect(res.send).toHaveBeenCalledWith('Rates already available in DB');
    });
});

替代写法:使用mockReturnValueOnce

如果只需要当前测试用例临时改变返回值,也可以用mockReturnValueOnce:

mockTestService.checkIfExistsInDB.mockReturnValueOnce(Promise.resolve(true));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 23:44:56