模拟日扩展
Mocking dayjs extend
在我需要测试的代码中我使用
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
dayjs.extend(utc);
dayjs().add(15, 'minute')
在我的测试中,我需要模拟 dayjs,以便在比较 jest
中的快照时始终具有相同的日期,所以我做到了
jest.mock('dayjs', () =>
jest.fn((...args) =>
jest.requireActual('dayjs')(
args.filter((arg) => arg).length > 0 ? args : '2020-08-12'
)
)
);
它失败了
TypeError: _dayjs.default.extend is not a function
不幸的是,这里的类似问题对我没有帮助。我怎么能同时模拟默认 dayjs
和 extend
?
随心所欲地模拟 dayjs,不要忘记按如下方式设置静态函数:
import dayjs from "dayjs";
jest.mock('dayjs', () =>
jest.fn((...args) =>
jest.requireActual('dayjs')(
args.filter((arg) => arg).length > 0 ? args : '2020-08-12'
)
)
);
dayjs.extend = jest.fn();
您 可以 为 dayjs
编写一个更全面的手动模拟,一个具有 extend
方法的模拟,但随后您将测试耦合到第 3 方接口。 “不要模拟你不拥有的东西” - 你最终将不得不在你的模拟中重新创建越来越多的 dayjs
界面,然后如果界面更改您的测试将继续通过,但您的代码将被破坏。或者,如果您决定切换到不同的时间库,则必须重写所有测试以手动模拟新界面。
相反,将时间视为依赖项。在您自己的模块中拥有您自己的功能,它只是将当前时间作为 Date
对象提供:
export const howSoonIsNow = () => new Date();
然后,当您需要创建一个 dayjs
对象时,从那个 开始(dayjs()
相当于 dayjs(new Date())
每个 the docs):
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { howSoonIsNow } from './path/to/noTimeLikeThePresent';
dayjs.extend(utc);
dayjs(howSoonIsNow()).add(15, 'minute');
现在在你的测试中你可以换掉你实际拥有的东西,而不必干扰 dayjs
:
import { howSoonIsNow } from './path/to/noTimeLikeThePresent';
jest.mock('./path/to/noTimeLikeThePresent');
howSoonIsNow.mockReturnValue(new Date(2020, 8, 12));
现在,如果 dayjs
的新版本以某种方式改变了您对它的使用,您的测试将失败并告诉您同样的信息。或者,如果您切换到不同的时间库(here's 使用 Moment 的示例),则不必重写所有测试,因此您可以确信自己已正确切换。
此外,FWIW 我一般不评价快照测试 - 它只是变成了变化检测,因不相关的变化而失败,并鼓励人们忽略测试结果并在任何失败时盲目地重新创建快照。根据您想从组件中看到的行为进行测试。
在我需要测试的代码中我使用
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
dayjs.extend(utc);
dayjs().add(15, 'minute')
在我的测试中,我需要模拟 dayjs,以便在比较 jest
中的快照时始终具有相同的日期,所以我做到了
jest.mock('dayjs', () =>
jest.fn((...args) =>
jest.requireActual('dayjs')(
args.filter((arg) => arg).length > 0 ? args : '2020-08-12'
)
)
);
它失败了
TypeError: _dayjs.default.extend is not a function
不幸的是,这里的类似问题对我没有帮助。我怎么能同时模拟默认 dayjs
和 extend
?
随心所欲地模拟 dayjs,不要忘记按如下方式设置静态函数:
import dayjs from "dayjs";
jest.mock('dayjs', () =>
jest.fn((...args) =>
jest.requireActual('dayjs')(
args.filter((arg) => arg).length > 0 ? args : '2020-08-12'
)
)
);
dayjs.extend = jest.fn();
您 可以 为 dayjs
编写一个更全面的手动模拟,一个具有 extend
方法的模拟,但随后您将测试耦合到第 3 方接口。 “不要模拟你不拥有的东西” - 你最终将不得不在你的模拟中重新创建越来越多的 dayjs
界面,然后如果界面更改您的测试将继续通过,但您的代码将被破坏。或者,如果您决定切换到不同的时间库,则必须重写所有测试以手动模拟新界面。
相反,将时间视为依赖项。在您自己的模块中拥有您自己的功能,它只是将当前时间作为 Date
对象提供:
export const howSoonIsNow = () => new Date();
然后,当您需要创建一个 dayjs
对象时,从那个 开始(dayjs()
相当于 dayjs(new Date())
每个 the docs):
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { howSoonIsNow } from './path/to/noTimeLikeThePresent';
dayjs.extend(utc);
dayjs(howSoonIsNow()).add(15, 'minute');
现在在你的测试中你可以换掉你实际拥有的东西,而不必干扰 dayjs
:
import { howSoonIsNow } from './path/to/noTimeLikeThePresent';
jest.mock('./path/to/noTimeLikeThePresent');
howSoonIsNow.mockReturnValue(new Date(2020, 8, 12));
现在,如果 dayjs
的新版本以某种方式改变了您对它的使用,您的测试将失败并告诉您同样的信息。或者,如果您切换到不同的时间库(here's 使用 Moment 的示例),则不必重写所有测试,因此您可以确信自己已正确切换。
此外,FWIW 我一般不评价快照测试 - 它只是变成了变化检测,因不相关的变化而失败,并鼓励人们忽略测试结果并在任何失败时盲目地重新创建快照。根据您想从组件中看到的行为进行测试。