[英]Mocking setTimeout with jest
我有一个用 React.JS 制作的网站,它不断地为正在发生的所有事情 [和任何事情] 发出事件。 例如,用户在表单中输入内容,发出事件。 用户将焦点放在一个字段上并且一段时间内不做任何事情,我们再次发出一个事件。 这个想法是了解客户的行为。
我有一个以前用作<Button onClick={(e)=>handler(e)}/>
的按钮。 我不得不去抖动按钮并将其更改为<Button onClick={(e)=>setTimeout(handler(e), 1000)}/>
。 否则,用户不明白发生了什么。
现在,我正在尝试将测试调整为:
it('displays similar listings', async () => {
const renderResult = renderVdp(renderParams);
await new Promise((resolve) => setTimeout(resolve, 1000));
await waitFor(async () => {
expect(renderResult.getAllByText('2017 BMW M3')).toHaveLength(4);
});
});
我能够通过添加await new Promise((resolve) => setTimeout(resolve, 1000));
来保持原始测试的工作。 在相关测试之前。 没有它,测试会收到下一个发出的事件,这不是作为单击按钮的响应而发出的事件。
我想使用开玩笑的计时器 mocking 或类似的东西,而不是在我的测试中实际引入延迟。 我曾尝试使用jest.useFakeTimers()
,但它不能按我的需要工作。 我的期望失败了。
建议?
一旦你使用了假计时器,你就可以控制何时运行它们。 渲染后尝试运行它们:
it('displays similar listings', async () => {
jest.useFakeTimers()
const renderResult = renderVdp(renderParams);
jest.runAllTimers();
expect(renderResult.getAllByText('2017 BMW M3')).toHaveLength(4);
});
如果这不起作用,您可以随时使用更“激进”的模拟:
global.setTimeout = jest.fn(cb => cb());
我会在测试设置beforeEach
/ beforeAll
中执行此操作,并在测试拆解afterEach
/ afterAll
中回滚到原始 setTimeout
如果我看不到代码,很难说出测试应该是什么样子。
如果您的组件有点像这样工作:
const SetTimeoutComponent = () => {
const [content, setContent] = React.useState<string[]>([]);
const handleButtonClick = (event: React.MouseEvent<HTMLElement>) => {
setContent([
'2017 BMW M3',
'2017 BMW M3',
'2017 BMW M3',
'2017 BMW M3'
])
}
return (
<div>
<button onClick={(e)=>setTimeout(() => handleButtonClick(e), 1000)}>
Set timeout with state update
</button>
<div>
{content.map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
</div>
);
};
然后您可以按如下方式对其进行测试:
it('displays similar listings', async () => {
render(<TestedComponent />);
const setTimeoutButton = screen.getByRole('button');
jest.useFakeTimers();
fireEvent.click(setTimeoutButton);
act(() => {
jest.runAllTimers();
});
expect(screen.getAllByText('2017 BMW M3')).toHaveLength(4);
jest.useRealTimers();
});
您可以在我的帖子中查看更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.