React 單元測試寫法範例 — 如何正確等待 element 觸發 / 渲染
教你寫如何正確等待「元素」來測試
2024/05/28
重點
- 組件用
findByOOO
來 await 等待。 - 判斷(expect) 才用
waitFor
來 await 等待。
實作
-
核心用法大致如下
// 先用 await findByOOO 拿到需要互動的組件 const joinButton = await screen.findByTestId("join-button"); // await 完確認拿到之後,再去做互動、檢查...等 userEvent.click(joinButton); // 驗證測項,把 expect 裡面的 callback 呼叫後 return 出來即可 await waitFor(() => ( expect(...).toEqual(...) ))
-
以下為完整測試案例的範例
it("Join should be called.", () => { const spyJoin = jest.spyOn(Repository.prototype, "join").mockResolvedValue({} as any); // given given_some_api(data); await when_render(); // when userEvent.click(screen.getByTestId("confirm-button")); // 這個是需要等待狀態變化才抓得到的組件 const joinButton = await screen.findByTestId("join-button"); userEvent.click(joinButton); // then const request: Request = { id: 1, name: 'hi' }; await waitFor(() => ( expect(spyJoin).toHaveBeenCalledWith(request) )); await waitFor(() => { expect(screen.getByText("Join Successfully")).toBeInTheDocument(); }); })
容易搞混的誤區
-
waitFor 搭配需等待 element 的行為觸發 >> 這次就是卡在這個坑,讓測試時好時壞。推測是因為這個寫法做測試的組件等待順序不穩定,在測試資源不足的情況下,特別容易出錯(不定時出錯)
// ❌ await waitFor(() => { userEvent.click(...) }) // ✅ const el = await screen.findByOOO(); userEvent.click(el);