![](/img/trans.png)
[英]How to test react-dropzone with Jest and react-testing-library?
[英]How to test react-toastify with jest and react-testing-library
我有一個帶有某種形式的屏幕,在提交時,我使用 axios 將請求發送到后端。 成功收到響應后,我用 react-toastify 展示了一個 toast。 非常直接的屏幕。 但是,當我嘗試使用 jest 和 react 測試庫的集成測試來測試這種行為時,我似乎無法讓 toast 出現在 DOM 上。
我有一個像這樣的實用程序渲染器來渲染我正在使用 toast 容器測試的組件:
import {render} from "@testing-library/react";
import React from "react";
import {ToastContainer} from "react-toastify";
export const renderWithToastify = (component) => (
render(
<div>
{component}
<ToastContainer/>
</div>
)
);
在測試本身中,我使用 react-testing-library 填寫表單,按下提交按鈕,然后等待 toast 出現。 我正在使用模擬服務人員來模擬響應。 我確認響應返回正常,但由於某種原因,toast 拒絕出現。 我目前的測試如下:
expect(await screen.findByRole("alert")).toBeInTheDocument();
我正在尋找具有角色警報的元素。 但這似乎行不通。 另外,我嘗試做這樣的事情:
...
beforeAll(() => {
jest.useFakeTimers();
}
...
it("test", () => {
...
act(() =>
jest.runAllTimers();
)
expect(await screen.findByRole("alert")).toBeInTheDocument();
}
我對 JS 有點陌生,問題可能是由於 axios 和 react-toastify 的異步性質,但我不知道如何測試這種行為。 我嘗試了很多東西,包括 mocking 定時器和運行它們,mocking 定時器和推進它們,而不是 mocking 它們和等待等。我什至試圖讓它正常工作,但我無法正常工作。 加上這似乎是一個實現細節,所以我認為我不應該是 mocking 。
我認為問題是我在 axios promise 解決之后顯示吐司,所以計時器不知何故感到困惑。
我試圖搜索很多地方,但未能找到答案。
提前致謝。
謝謝@Estus Flask,但問題要愚蠢得多:) 我必須在我的組件之前渲染 ToastContainer,如下所示:
import {render} from "@testing-library/react";
import React from "react";
import {ToastContainer} from "react-toastify";
export const renderWithToastify = (component) => {
return (
render(
<div>
<ToastContainer/>
{component}
</div>
)
);
};
然后,測試很簡單,我只需要等待 toast 的標題:
expect(await screen.findByText("alert text")).toBeInTheDocument();
findByRole 似乎由於某種原因不起作用,但我太累了,無法深入挖掘:) 我不必使用任何假計時器或刷新承諾。 顯然,當您使用 await 和 finBy* 查詢時,RTL 已經執行了這些操作,只是渲染順序是錯誤的。
我要做的是從react-toastify
模擬該方法以監視該方法以查看調用它的內容,而不是屏幕上出現的實際組件:
// setupTests.js
jest.mock('react-toastify', () => {
const actual = jest.requireActual('react-toastify');
Object.assign(actual, {toast: jest.fn()});
return actual;
});
然后在實際測試中:
// test.spec.js
import {toast} from 'react-toastify';
const toastCalls = []
const spy = toast.mockImplementation((...args) => {
toastCalls.push(args)
}
)
describe('...', () => {
it('should ...', () => {
// do something that calls the toast
...
// then
expect(toastCalls).toEqual(...)
}
}
)
另一個建議是將這個mockImplementation
放入一個單獨的輔助函數中,您可以輕松調用您需要的測試。 這是一種熊骨方法:
function startMonitoring() {
const monitor = {toast: [], log: [], api: [], navigation: []};
toast.mockImplementation((...args) => {
monitor.toast.push(args);
});
log.mockImplementation((...args) => {
monitor.log.push(args);
});
api.mockImplementation((...args) => {
monitor.api.push(args);
});
navigation.mockImplementation((...args) => {
monitor.navigation.push(args);
});
return () => monitor;
}
it('should...', () => {
const getSpyCalls = startMonitoring();
// do something
expect(getSpyCalls()).toEqual({
toast: [...],
log: [...],
api: [...],
navigation: [...]
});
});
在這里,解決方案是使用 getByText:
await waitFor(() => {
expect(screen.getByText(/Logged!/i)).toBeTruthy()
})
為了在您無權訪問 DOM 時使用模擬(如 Redux 副作用),您可以執行以下操作:
import { toast } from 'react-toastify'
jest.mock('react-toastify', () => ({
toast: {
success: jest.fn(),
},
}))
expect(toast.success).toHaveBeenCalled()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.