[英]Testing a callback function in Jest
不用說,該應用程序比這復雜得多,但要點是相同的。 我無法對應用程序進行重大更改,例如導入/導出 onSuccess 函數或更改為基於類的組件。
單擊按鈕會啟動 Login 函數,我在其中傳入 onSuccess 函數。 我想監視分析函數以確保它被調用,但在我的測試中我無法調用 onSuccess 函數
理想情況下,我想做這樣的事情:
test("analyze should be called", () => {
let analyzeSpy = jest.spyOn(Analytics, "analyze");
onSuccess() //<- cannot do this
expect(analyzeSpy).toHaveBeenCalledTimes(1);
});
這是應用程序:
import Analytics from "./Analytics";
export function Login({ onLoginSuccess }) {
setTimeout(function () {
console.log("TIMEOUT OVER");
onLoginSuccess();
}, 2000);
}
function App() {
function handleClick() {
console.log("Login");
Login({
onLoginSuccess: onSuccess,
});
}
function onSuccess() {
console.log("Login success");
Analytics.analyze();
}
return (
<>
<button
onClick={() => {
handleClick();
}}
>
Login
</button>
</>
);
}
export default App;
這是 Analytics.js:
export default {
analyze: () => {
console.log("Analysis done");
},
};
我該如何測試?
使用react-dom
模塊的render()
方法將您的組件渲染到js-dom
提供的文檔中。
使用document.querySelector('button')
獲取按鈕 dom,調度鼠標點擊事件。
使用jest.useFakeTimers()
來使用標准定時器函數( setTimeout
)的假版本。
分派點擊事件后,使用jest.advanceTimersByTime(2000)
執行宏任務隊列(由setTimeout
排隊的任務)。
然后,做一個斷言。
例如
App.jsx
:
import React from 'react';
import Analytics from './Analytics';
export function Login({ onLoginSuccess }) {
setTimeout(function () {
console.log('TIMEOUT OVER');
onLoginSuccess();
}, 2000);
}
function App() {
function handleClick() {
console.log('Login');
Login({
onLoginSuccess: onSuccess,
});
}
function onSuccess() {
console.log('Login success');
Analytics.analyze();
}
return (
<>
<button
onClick={() => {
handleClick();
}}
>
Login
</button>
</>
);
}
export default App;
App.test.jsx
:
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { act } from 'react-dom/test-utils';
import App from './App';
import Analytics from './Analytics';
describe('68400320', () => {
let container = null;
beforeEach(() => {
// setup a DOM element as a render target
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
// cleanup on exiting
unmountComponentAtNode(container);
container.remove();
container = null;
});
test('should pass', () => {
const analyzeSpy = jest.spyOn(Analytics, 'analyze');
jest.useFakeTimers();
act(() => {
render(<App />, container);
});
const button = document.querySelector('button');
act(() => {
button?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
jest.advanceTimersByTime(2000);
});
expect(analyzeSpy).toBeCalledTimes(1);
});
});
測試結果:
PASS examples/68400320/App.test.jsx (8.12 s)
68400320
✓ should pass (52 ms)
console.log
Login
at handleClick (examples/68400320/App.jsx:13:13)
console.log
TIMEOUT OVER
at examples/68400320/App.jsx:6:13
console.log
Login success
at onSuccess (examples/68400320/App.jsx:19:13)
console.log
Analysis done
at Object.analyze (examples/68400320/Analytics.js:3:13)
--------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
--------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
Analytics.js | 100 | 100 | 100 | 100 |
App.jsx | 100 | 100 | 100 | 100 |
--------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.666 s, estimated 10 s
Ran all test suites related to changed files.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.