Jav*_*kie 4 unit-testing reactjs react-testing-library react-hooks
我的组件:
import React from 'react'
const TestAsync = () => {
const [counter, setCounter] = React.useState(0)
const delayCount = () => (
setTimeout(() => {
setCounter(counter + 1)
}, 500)
)
return (
<>
<h1 data-testid="counter">{ counter }</h1>
<button data-testid="button-up" onClick={delayCount}> Up</button>
<button data-testid="button-down" onClick={() => setCounter(counter - 1)}>Down</button>
</>
)
}
export default TestAsync
Run Code Online (Sandbox Code Playgroud)
我的测试文件:
describe("Test async", () => {
it("increments counter after 0.5s", async () => {
const { getByTestId, getByText } = render(<TestAsync />);
fireEvent.click(getByTestId("button-up"));
const counter = await waitForElement(() => getByTestId("counter"));
expect(counter).toHaveTextContent("1");
});
});
Run Code Online (Sandbox Code Playgroud)
运行测试文件后,我收到错误消息:
Expected element to have text content:
1
Received:
0
Run Code Online (Sandbox Code Playgroud)
我有点困惑为什么我用来waitForElement获取元素但为什么元素仍然具有旧值?
React-testing-lib 版本 9.3.2
sli*_*wp2 11
首先,waitForElement已被弃用。使用find*查询(首选: https: //testing-library.com/docs/dom-testing-library/api-queries#findby)或waitFor改用: https: //testing-library.com/docs/dom-testing-库/api-async#waitfor
现在,我们使用waitFor:
\n\n\n
waitFor可能会多次运行回调,直到达到超时。
您需要将断言语句包装在waitFor. 这样就waitFor可以多次运行回调。如果将expect(counter).toHaveTextContent(\'1\');语句放在语句之外和之后waitFor,那么它只会运行一次。断言运行时 React 尚未更新。
为什么RTL会多次运行回调(超时前每隔一段时间运行回调)?
\nRTL 使用MutationObserver来监视对 DOM 树所做的更改,请参阅此处。记住,我们的测试环境是jsdom,它支持MutationObserver,看这里。
这意味着当 React 更新状态并将更新应用到 DOM 时,可以检测到 DOM 树的更改,并且 RTL 将再次运行回调(包括断言)。当 React 组件状态被应用并变得稳定时,回调的最后一次运行将被视为测试的最终断言。如果断言失败,则报告错误,否则测试通过。
\n所以工作示例应该是:
\nindex.tsx:
import React from \'react\';\n\nconst TestAsync = () => {\n const [counter, setCounter] = React.useState(0);\n\n const delayCount = () =>\n setTimeout(() => {\n setCounter(counter + 1);\n }, 500);\n\n return (\n <>\n <h1 data-testid="counter">{counter}</h1>\n <button data-testid="button-up" onClick={delayCount}>\n Up\n </button>\n <button data-testid="button-down" onClick={() => setCounter(counter - 1)}>\n Down\n </button>\n </>\n );\n};\n\nexport default TestAsync;\nRun Code Online (Sandbox Code Playgroud)\nindex.test.tsx:
import { fireEvent, render, waitFor } from \'@testing-library/react\';\nimport React from \'react\';\nimport TestAsync from \'.\';\nimport \'@testing-library/jest-dom/extend-expect\';\n\ndescribe(\'Test async\', () => {\n it(\'increments counter after 0.5s\', async () => {\n const { getByTestId } = render(<TestAsync />);\n\n fireEvent.click(getByTestId(\'button-up\'));\n\n await waitFor(() => {\n const counter = getByTestId(\'counter\');\n expect(counter).toHaveTextContent(\'1\');\n });\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n测试结果:
\nimport React from \'react\';\n\nconst TestAsync = () => {\n const [counter, setCounter] = React.useState(0);\n\n const delayCount = () =>\n setTimeout(() => {\n setCounter(counter + 1);\n }, 500);\n\n return (\n <>\n <h1 data-testid="counter">{counter}</h1>\n <button data-testid="button-up" onClick={delayCount}>\n Up\n </button>\n <button data-testid="button-down" onClick={() => setCounter(counter - 1)}>\n Down\n </button>\n </>\n );\n};\n\nexport default TestAsync;\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
15556 次 |
| 最近记录: |