dep:
dev/dep:
myHook.jsfunction useMyHook(){
const [isGood, setIsGood] = useState(false);
useEffect(() => {
async function getIsGood(){
const isGood = await apiClient.getIsGood();
setIsGood(isGood);
}
}, []);
return {isGood}
}
test.specs.jsimport sinon from 'sinon';
import useMyHook from '...';
import apiClient from '...';
import { renderHook } from '@testing-library/react-hooks';
describe('', () => {
const sandbox = sinon.createSandbox();
it('', async () => {
// arrange
// always resolve false;
const stub = sandbox.stub(apiClient, 'getIsGood');
stub.resolves(false);
// act
const { result, waitForNextUpdate } = renderHook(() => useMyHook());
await waitForNextUpdate();
expect(result.current.isGood).toBeFalsy();
});
});
test passes
Async timeout. Codes stop at await waitForNextUpdate();
I read the docs and found one comment here https://github.com/testing-library/react-hooks-testing-library/issues/211#issuecomment-548538370. It seems like the component will not be re-rendered since the state(isGood) is not changed(always set to false). So that await waitForNextUpdate() is never resolved.
I still want to test some behaviours like apiClient.getIsGood is called and isGood will be set properly by the result from the apiClient.getIsGood.
However with waitForNextUpdate I can't do it since component is not re-rendered and without waitForNextUpdate, the expected assertions is evaluated before the useEffect which is logically wrong.
Is there a solution to this problem?
Thanks!
Hi @Kiiiwiii,
sorry for the delay in responding. Unfortunately if there is no render, the promise won't resolve (it is literally waiting for the next render to fire).
You could put a small timeout in the test and catch the timeout error so it doesn't wait forever for an render that is not coming:
const { result, waitForNextUpdate } = renderHook(() => useMyHook());
try {
await waitForNextUpdate({ timeout: 100 } );
} catch(err) {
expect(err.timeout).toBeTruthy();
}
expect(result.current.isGood).toBeFalsy();
_Note: completely untested_
@mpeyper thanks for your response. This walk around works!
I fixed this for myself by waiting for the assertion to become true, i.e.
await wait(() => expect(spy).toHaveBeenCalledTimes(1))
Most helpful comment
I fixed this for myself by waiting for the assertion to become true, i.e.