use*_*707 8 javascript testing reactjs jestjs react-testing-library
我有一个非常简单的组件,我试图模拟 API 调用来获取一些稍有延迟的电影。
我想编写一个测试来测试电影是否被收集然后渲染到屏幕上。
我试图用来screen.getAllByTestId
做到这一点,但它总是失败。就好像它没有重新渲染,因此没有获得更新的更改。
我在元素上添加了一个 testid,并且可以在 DOM 中看到它们。
任何人都可以帮忙解释为什么他们出现后找不到他们吗?
这是完整的组件代码...
import './App.css';
import { useEffect, useState } from 'react';
function App() {
const [movies, setMovies] = useState([]);
useEffect(() => {
// simulate API call to get
setTimeout(() => {
const movies = [{ title: 'Titanic' }, { title: 'Back To The Future' }];
setMovies(movies);
}, 1000);
}, []);
return (
<div>
{movies.length > 0 && (
<div>
{movies.map((x) => (
<div data-testid='movies'>{x.title}</div>
))}
</div>
)}
</div>
);
}
export default App;
Run Code Online (Sandbox Code Playgroud)
这是完整的测试代码...
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const movieTiles = screen.getAllByTestId('movies');
expect(movieTiles).toHaveLength(2);
});
Run Code Online (Sandbox Code Playgroud)
这是测试中的错误
当您的代码使用计时器(, , , )时,您应该使用假计时器。setTimeout
setInterval
clearTimeout
clearInterval
用于jest.advanceTimersByTime(1000)
将时间提前 1000 毫秒。
不要忘记act()
辅助函数:
\n\n在编写 UI 测试时,渲染、用户事件或数据获取等任务可以被视为与用户界面交互的 \xe2\x80\x9cunits\xe2\x80\x9d 。react-dom/test-utils 提供了一个名为的助手
\nact()
,确保在做出任何断言之前与这些 \xe2\x80\x9cunits\xe2\x80\x9d 相关的所有更新都已被处理并应用到 DOM:
由于我们setState
提前 1000 毫秒运行将更改组件状态的函数,因此我们必须将此操作 ( jest.advanceTimersByTime(1000)
) 包装在act()
函数中。
否则,您将收到警告:
\n\n\n警告:测试内应用程序的更新未包含在 act(...) 中。
\n
\n\n测试时,导致 React 状态更新的代码应包装到 act(...) 中:
\n
例如
\nApp.jsx
:
import React, { useEffect, useState } from \'react\';\n\nfunction App() {\n const [movies, setMovies] = useState([]);\n\n useEffect(() => {\n setTimeout(() => {\n const movies = [{ title: \'Titanic\' }, { title: \'Back To The Future\' }];\n setMovies(movies);\n }, 1000 * 10);\n }, []);\n\n return (\n <div>\n {movies.length > 0 && (\n <div>\n {movies.map((x, idx) => (\n <div key={idx} data-testid="movies">\n {x.title}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport default App;\n
Run Code Online (Sandbox Code Playgroud)\nApp.test.jsx
:
import { render, screen, act } from \'@testing-library/react\';\nimport React from \'react\';\nimport App from \'./App\';\n\ndescribe(\'68460159\', () => {\n test(\'renders learn react link\', async () => {\n jest.useFakeTimers();\n render(<App />);\n act(() => {\n jest.advanceTimersByTime(1000 * 10);\n });\n const movieTiles = screen.getAllByTestId(\'movies\');\n expect(movieTiles).toHaveLength(2);\n jest.runOnlyPendingTimers();\n jest.useRealTimers();\n });\n});\n
Run Code Online (Sandbox Code Playgroud)\n测试结果:
\n PASS examples/68460159/App.test.jsx (7.878 s)\n 68460159\n \xe2\x9c\x93 renders learn react link (33 ms)\n\n----------|---------|----------|---------|---------|-------------------\nFile | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------|---------|----------|---------|---------|-------------------\nAll files | 100 | 100 | 100 | 100 | \n App.jsx | 100 | 100 | 100 | 100 | \n----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests: 1 passed, 1 total\nSnapshots: 0 total\nTime: 8.678 s, estimated 10 s\n
Run Code Online (Sandbox Code Playgroud)\n