如何使用Jest模拟localForage.getItem的Promise拒绝以测试get方法的Catch代码块?
如何测试Jest中localForage.getItem的Promise拒绝场景?
看起来你的测试代码在mock localForage.getItem的方式上出了问题,导致实际调用的还是原方法(或者默认的mock实现),所以Promise被resolved而不是rejected,进而触发了未处理的拒绝错误。我来帮你修正这个测试,同时解释问题所在:
问题分析
你的测试代码里jest.fn(localforage.getItem).mockRejectedValue(new Error())这一行是错误的:
jest.fn(originalFn)会创建一个新的mock函数,但不会替换原对象上的方法。也就是说,你的get函数调用的依然是原本的localforage.getItem,而不是你刚创建的mock函数。- 另外,测试中没有用
await等待expect(...).rejects完成,Jest可能在Promise处理结束前就结束测试,导致未捕获的Promise拒绝。
正确的测试方案
根据你的代码结构(假设get是某个类的方法,依赖this.localForage),我们需要正确mock localForage的实例或者模块:
情况1:get是类的方法(依赖注入localForage)
如果你的代码是类的形式,比如:
import type LocalForage from 'localforage'; class StorageService { private localForage: LocalForage; constructor(localForageInstance: LocalForage) { this.localForage = localForageInstance; } async get<T>(key: string): Promise<T | null> { if (!key) { return Promise.reject(new Error('There is no key to get!')); } try { return await this.localForage.getItem(key); } catch (err) { throw new Error(`The key (${key}) isn't accessible.`); } } }
对应的测试代码应该这样写:
import { StorageService } from './storage-service'; import localforage from 'localforage'; // 先mock整个localforage模块 jest.mock('localforage'); test('get方法在localForage.getItem拒绝时抛出正确错误', async () => { const testKey = 'fghgdfghfghfdh'; const expectedError = new Error(`The key (${testKey}) isn't accessible.`); // 将mock后的getItem方法设置为拒绝状态 (localforage.getItem as jest.Mock).mockRejectedValue(new Error('Mocked failure')); // 创建类实例,传入mock的localforage const storageService = new StorageService(localforage); // 用await等待Promise处理完成,确保Jest捕获拒绝情况 await expect(storageService.get(testKey)).rejects.toThrow(expectedError); });
情况2:get是独立函数(直接导入localForage)
如果你的get函数是直接使用导入的localforage:
import localforage from 'localforage'; async function get<T>(key: string): Promise<T | null> { if (!key) { return Promise.reject(new Error('There is no key to get!')); } try { return await localforage.getItem(key); } catch (err) { throw new Error(`The key (${key}) isn't accessible.`); } }
测试代码类似,只需要调整调用方式:
import { get } from './your-file-path'; import localforage from 'localforage'; jest.mock('localforage'); test('get函数在localForage.getItem拒绝时抛出正确错误', async () => { const testKey = 'fghgdfghfghfdh'; const expectedError = new Error(`The key (${testKey}) isn't accessible.`); (localforage.getItem as jest.Mock).mockRejectedValue(new Error('Mocked failure')); await expect(get(testKey)).rejects.toThrow(expectedError); });
关键注意事项
- 必须mock整个模块:用
jest.mock('localforage')让Jest替换所有对localforage的引用为mock对象,这样才能控制getItem的行为。 - 类型断言:因为TypeScript不知道
localforage.getItem已经被mock,所以需要用as jest.Mock来告诉TypeScript这是一个mock函数。 - 等待Promise完成:一定要用
await配合expect(...).rejects,否则Jest会在Promise处理结束前结束测试,引发未处理的Promise拒绝错误。
内容的提问来源于stack exchange,提问作者BuZZ-dEE
相关产品推荐
相关产品推荐

