Vitest报错:mock模块未定义formatWeatherData导出求助
解决Vitest Mock模块时"formatWeatherData导出未定义"的错误
问题场景
我有一个格式化天气API数据的函数formatWeatherData,想通过MockgetWeatherData接口调用生成固定测试数据,单独验证格式化逻辑。但运行Vitest测试时抛出错误:
Error: [vitest] No "formatWeatherData" export is defined on the "../controller/weatherApiController.ts" mock. Did you forget to return it from "vi.mock"?
相关代码如下:
weatherApiController.ts(注意:原代码存在循环导入问题,需删除开头无效的import)
// 删掉此行循环导入:import { getWeatherData, formatWeatherData} from '../controller/weatherApiController' import { describe, expect, vi, test } from 'vitest' export async function formatWeatherData(start: String, end: String){ let data = await getWeatherData(start, end) let formattedTemps = [] for(let i = 0; i < data.days.length; i++){ formattedTemps.push({datetime: data.days[i]['datetime'], tempmax: data.days[i]['tempmax'], tempmin: data.days[i]['tempmin']}) } return formattedTemps } export async function getWeatherData(start: String, end: String) { try{ let response = await fetch(`https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/Wermelskirchen/${start}/${end}?unitGroup=metric&include=days%2Ccurrent&key=<apiKey>&contentType=json`); if(!response.ok){ throw new Error(`HTTP Error! Status: ${response.status}`); } let data = await response.json() return data }catch(error){ console.error(error) return null } }
原测试代码(存在问题)
test('mock3', async()=> { let expected = [ { datetime: '2023-03-12', tempmax: 10.4, tempmin: -0.2 }, { datetime: '2023-03-13', tempmax: 15.4, tempmin: 9.1 } ] vi.mock('../controller/weatherApiController.ts', async() => { const actual = await vi.importActual("../controller/weatherApiController.ts") return { actual, getWeatherData: async() => { number: 3 }, formatWeatherData: async() => { number:4 } } }); const result = await formatWeatherData('2023-03-12', '2023-03-13') expect(result).toEqual(expected) })
错误原因
- 模块导出结构错误:在
vi.mock返回对象中,你将actual作为一个属性返回,而非展开其导出内容,导致原模块的formatWeatherData未被正确暴露。 - 不必要的Mock目标:
formatWeatherData是你要测试的核心函数,不需要Mock它,应该保留原实现,仅Mock依赖的getWeatherData。 - Mock返回值格式不符:当前
getWeatherData的Mock返回{number:3},完全不符合formatWeatherData所需的包含days数组的结构,会导致后续循环逻辑报错。
修复方案
按以下规则修改测试代码:
- 用对象展开运算符
...actual导入原模块的所有导出,确保formatWeatherData能正常访问 - 仅替换
getWeatherData的实现,返回符合API格式的模拟数据 - 移除对
formatWeatherData的Mock,保留原函数逻辑用于测试
完整修复后的测试代码
import { describe, expect, vi, test } from 'vitest' import { formatWeatherData } from '../controller/weatherApiController' // vi.mock需放在模块顶部/测试外部,确保模块加载时生效 vi.mock('../controller/weatherApiController.ts', async () => { const actual = await vi.importActual('../controller/weatherApiController.ts') return { ...actual, // 展开原模块所有导出,保留formatWeatherData原实现 getWeatherData: async () => { // 返回与真实API结构一致的模拟数据 return { days: [ { datetime: '2023-03-12', tempmax: 10.4, tempmin: -0.2 }, { datetime: '2023-03-13', tempmax: 15.4, tempmin: 9.1 } ] } } } }) test('测试formatWeatherData格式化逻辑', async () => { const expected = [ { datetime: '2023-03-12', tempmax: 10.4, tempmin: -0.2 }, { datetime: '2023-03-13', tempmax: 15.4, tempmin: 9.1 } ] const result = await formatWeatherData('2023-03-12', '2023-03-13') expect(result).toEqual(expected) })
内容的提问来源于stack exchange,提问作者LePa
相关产品推荐
相关产品推荐

