Set Immediate() to rescue - testing components with async componentDidMount()
unit-testing react components using Sinon
Table of contents
Scenario
we had a React class-based components on an older project and while implementing the feature change, we ended up calling an API from ComponentDidMount(). This made this function to be async since it involves a network call.
Sample code
async componentDidMount() {
const response = await CommonService.sampleapi(baseApiUrl);
}
Problem
so started testing the component using sinon, mocked the API and rendered the component using shallow and await keywords.
But when I tried to assert the mock call count and state it was always failing. Though I can verify the mocks are working properly using logs, the assert statements that verify the mock CallCount was always 0.
I was searching for something similar to waitFor(), and I ended up using wrapper.instance().update() for updating the state of the component -> but still it didn't help.
CommonService.sampleapi
.returns(Promise.resolve( true ));
let wrapper=await Enzyme.shallow(<componentexample {...defaultProps} />);
;
wrapper.instance().update()
expect(CommonService.sampleapi.callCount).to.equal(1);
Solution
The function that helped me to resolve the issue is assert the calls inside setImmediate() callbacks.
CommonService.sampleapi
.returns(Promise.resolve( true ));
let wrapper=await Enzyme.shallow(<componentexample {...defaultProps} />);
;
setImmediate(()=>
expect(CommonService.sampleapi.callCount).to.equal(1);
);
setImmediate
- if you want to queue the function behind whatever I/O event callbacks that are already in the event queue.
0
Testing a component that runs an async function from componentDidMount (or useEffect) must await a re-render before running assertions. wrapper. update is used to sync Enzyme's component tree before running assertions but doesn't wait for promises or force a re-render.
One approach is to use setImmediate, which runs its callback at the end of the event loop, allowing promises to resolve non-invasively.