My React-application has a component that fetches data to display from a remote server. In the pre-hooks era, componentDidMount()
was the place to go. But now I
I had that exact same problem, and ended up writing a library that solves this issue by mocking all the standards React Hooks.
Basically, act()
is a synchronous function, like useEffect
, but useEffect
executes an async function. There's no way that act() would be able to "wait" for that to execute. Fire and forget!
Article here: https://medium.com/@jantoine/another-take-on-testing-custom-react-hooks-4461458935d4
Library here: https://github.com/antoinejaussoin/jooks
To test your code, you would first need to extract your logic (the fetch, etc.) into a separate custom hook: something like:
const useFetchData = () => {
const [ state, setState ] = useState(0);
useEffect(() => {
fetchData().then(setState);
});
return state;
}
Then, using Jooks, your test would look like:
import init from 'jooks';
[...]
describe('Testing my hook', () => {
const jooks = init(() => useFetchData());
// Mock your API call here, by returning 'some mocked value';
it('Should first return 0', () => {
const data = jooks.run();
expect(data).toBe(0);
});
it('Then should fetch the data and return it', async () => {
await jooks.mount(); // Fire useEffect etc.
const data = jooks.run();
expect(data).toBe('some mocked value');
});
});