如何为无返回值函数编写Jest测试用例?以及如何测试获取过去12个月的getDateRange函数?
测试无返回值函数及
getDateRange的Jest方案 嘿,我来帮你搞定这两个问题——先聊聊无返回值函数的测试思路,再针对你的getDateRange函数写具体的测试方案。
一、无返回值函数的测试思路
无返回值的函数通常是通过修改外部状态、调用依赖函数、产生副作用(比如控制台输出、DOM操作)来完成工作的,所以测试时不用盯着返回值,而是要关注这些"结果痕迹":
- 检查它修改的对象/变量是否符合预期(比如你的函数修改了
this.months) - 用Jest的mock功能,验证它调用的依赖函数是否被正确调用(比如如果函数里调用了
fetch,可以mockfetch并检查调用参数) - 如果有控制台输出这类副作用,可以监听
console.log来验证输出内容
二、针对getDateRange函数的测试方案
首先得先指出你原函数里的几个小问题,不然测试跑不起来:
- 循环条件
i >= 13是反的,应该是i >= -12(这样才能遍历过去12个月) push的语法错误,应该是push({ dateLong: previousMonth })- 假设你用的是
luxon库的DateTime(因为原生Date没有add方法),我会基于这个修正函数后写测试
修正后的calculateDateRange.js
import { DateTime } from "luxon"; export function getDateRange() { const today = new Date(); this.months = []; // 遍历过去12个月(从上个月开始,往前数11个月,共12个) for (let i = -1; i >= -12; i--) { const previousMonth = DateTime.fromJSDate(today).plus({ months: i }); const firstDayOfMonth = previousMonth.startOf('month'); // 确保是当月第一天 if (firstDayOfMonth.year >= 2020) { this.months.push({ dateLong: firstDayOfMonth.toJSDate() }); } } }
编写Jest测试用例
创建calculateDateRange.test.js,核心思路是固定系统时间(避免测试结果随当前时间变化),然后检查this.months的内容是否符合预期:
import { getDateRange } from './calculateDateRange'; import { DateTime } from 'luxon'; // 测试前固定系统时间,避免动态时间影响结果 beforeEach(() => { jest.useFakeTimers().setSystemTime(new Date('2023-10-15')); }); // 测试后恢复真实时间 afterEach(() => { jest.useRealTimers(); }); describe('getDateRange', () => { it('should generate the last 12 months (starting from previous month) and filter those >=2020', () => { // 创建一个对象绑定this,因为函数用this.months存储结果 const resultObj = {}; getDateRange.call(resultObj); // 生成预期的月份列表:从2022-10-01到2023-09-01,共12个 const expectedMonths = Array.from({ length: 12 }, (_, index) => { const targetMonth = DateTime.fromJSDate(new Date('2023-10-15')) .plus({ months: -1 - index }) .startOf('month'); return { dateLong: targetMonth.toJSDate() }; }); // 比较日期时转成ISO字符串(Date对象直接比较是引用,不准确) const actualDates = resultObj.months.map(item => item.dateLong.toISOString()); const expectedDates = expectedMonths.map(item => item.dateLong.toISOString()); expect(actualDates).toEqual(expectedDates); }); it('should exclude all months before 2020', () => { // 固定时间为2019-05-10,此时过去12个月的年份都小于2020 jest.useFakeTimers().setSystemTime(new Date('2019-05-10')); const resultObj = {}; getDateRange.call(resultObj); // 预期数组为空,因为所有月份都不符合>=2020的条件 expect(resultObj.months).toEqual([]); }); });
测试要点说明
- 固定系统时间:用
jest.useFakeTimers().setSystemTime()把当前时间固定下来,这样每次测试的输入都是一致的,结果可重复 - 绑定this:因为你的函数用
this.months存储结果,所以需要用call方法把函数绑定到一个空对象上,方便后续检查结果 - 日期比较技巧:Date对象是引用类型,直接
expect(actual).toEqual(expected)会失败,所以转成ISO字符串或者时间戳(getTime())来比较
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

