[英]Testing a callback function in Jest
Needless to say, the app is a lot more complicated that this, but the gist is the same.不用说,该应用程序比这复杂得多,但要点是相同的。 I cannot make major changes to the App, such as import/export the onSuccess function or changing to a class based component.
我无法对应用程序进行重大更改,例如导入/导出 onSuccess 函数或更改为基于类的组件。
A button click kicks off the Login function, where I pass in an onSuccess function.单击按钮会启动 Login 函数,我在其中传入 onSuccess 函数。 I want to spy on the analyze function to make sure it is called, but in my test I have no way of calling the onSuccess function
我想监视分析函数以确保它被调用,但在我的测试中我无法调用 onSuccess 函数
Ideally I would like to do something like this:理想情况下,我想做这样的事情:
test("analyze should be called", () => {
let analyzeSpy = jest.spyOn(Analytics, "analyze");
onSuccess() //<- cannot do this
expect(analyzeSpy).toHaveBeenCalledTimes(1);
});
Here is the app:这是应用程序:
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;
This is Analytics.js:这是 Analytics.js:
export default {
analyze: () => {
console.log("Analysis done");
},
};
How can I test this?我该如何测试?
Use render()
method of react-dom
module to render your component into document provided by js-dom
.使用
react-dom
模块的render()
方法将您的组件渲染到js-dom
提供的文档中。
Use document.querySelector('button')
to get the button dom, dispatch a mouse click event.使用
document.querySelector('button')
获取按钮 dom,调度鼠标点击事件。
Use jest.useFakeTimers()
to use fake versions of the standard timer functions( setTimeout
).使用
jest.useFakeTimers()
来使用标准定时器函数( setTimeout
)的假版本。
After dispatching the click event, use jest.advanceTimersByTime(2000)
to executes the macro task queue (tasks queued by setTimeout
).分派点击事件后,使用
jest.advanceTimersByTime(2000)
执行宏任务队列(由setTimeout
排队的任务)。
Then, make an assertion.然后,做一个断言。
Eg例如
App.jsx
: 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
: 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);
});
});
test result:测试结果:
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.