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

如何用Jest测试日期?日期比较测试遇类型错误求助

问题

我正在编写测试用例,验证选中的日期是否大于当前日期。以下是待测试的React组件代码:

const [selectedDate, setSelectedDate] = useState<Moment>();

<TimeComponent>
  <SetTimeButton 
    data-testid="scheduleTime"
    onClick={() =>
      scheduleTimeHandler(
        selectedDate,
        timeSelect,
        setSelectedDate,
        setTimeDialog,
        setDisableConfirm
      )
    }
  />
  <DisplayDate data-testid="selectedDate">{selectedDate}</DisplayDate>
</TimeComponent>

这是我编写的Jest测试代码:

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import TimeComponent from './TimeComponent';

test('set schedule time', () => {
  render(
    //@ts-ignore
    <TimeComponent />
  );

  const mockDateObject = new Date();
  const scheduleTimeBtn = screen.queryByTestId('scheduleTime');
  const selectedDate = screen.queryByTestId('selectedDate');

  fireEvent.click(scheduleTimeBtn);

  expect(selectedDate).toBeGreaterThan(+mockDateObject);
});

执行测试时,expect语句中针对selectedDate出现如下错误:

expect(received).toBeGreaterThan(expected)

Matcher error: received value must be a number or bigint

Received has value: null

我知道这是因为selectedDate是HTML元素而非日期值,但不清楚如何将其转为日期值进行测试,请问我哪里出错了?

解决方案

你的测试代码存在两个核心问题,修正后即可正常运行:

1. 元素获取时机错误

你在点击按钮前就调用screen.queryByTestId('selectedDate')获取元素,此时组件还未触发状态更新,selectedDate为空,所以返回null。正确做法是在点击按钮后再获取目标元素,或者使用screen.getByTestId(它会自动等待元素渲染完成,比queryBy更适合处理交互后的异步更新场景)。

2. 未提取日期文本并转为可比较格式

queryByTestId返回的是DOM元素对象,而非日期值。你需要先提取元素的文本内容,再将其转换为与组件一致的Moment对象(或时间戳),才能进行日期比较。

修改后的测试代码

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import TimeComponent from './TimeComponent';
import moment from 'moment'; // 组件使用Moment类型,需引入对应库

test('set schedule time', () => {
  render(
    //@ts-ignore
    <TimeComponent />
  );

  const currentDate = moment(); // 用moment创建当前日期,与组件类型对齐
  const scheduleTimeBtn = screen.getByTestId('scheduleTime');

  fireEvent.click(scheduleTimeBtn);

  // 点击后获取元素,提取文本并转为Moment对象
  const selectedDateElement = screen.getByTestId('selectedDate');
  const selectedDate = moment(selectedDateElement.textContent);

  // 用moment内置的isAfter方法比较,更符合Moment类型的使用习惯
  expect(selectedDate.isAfter(currentDate)).toBe(true);
  
  // 也可以转换为时间戳用数值比较:
  // expect(selectedDate.valueOf()).toBeGreaterThan(currentDate.valueOf());
});

额外注意事项

  • 如果DisplayDate组件对日期做了自定义格式化(比如YYYY/MM/DD HH:mm),需要在moment解析时指定对应格式,避免解析错误:moment(selectedDateElement.textContent, 'YYYY/MM/DD HH:mm')。
  • 对于交互后必然出现的元素,优先使用getByTestId而非queryByTestId,前者会自动等待元素渲染,减少测试不稳定的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 15:25:15