Component:
export const fetchList = () => {
return API.get(AMPLIFY_ENPOINTS.default, API_URLS.list, { response: true });
}
const List: React.FC = () => {
const dispatch = useDispatch();
const setError = useError();
useEffect(() => {
fetchList()
.then((response) => {
if (response && response.data?.length) {
dispatch(setList(response.data));
}
})
.catch((error) => {
setError(error);
});
}, [])
}
Test:
it('should fetch list', async () => {
const wrapper = mount(
<Provider store={store}>
<List />
</Provider>
);
API.get = jest.fn().mockImplementation(() => Promise.resolve({ data: mockList }));
const response = await fetchList();
console.log(store.getActions(), response); // HERE IS THE ISSUE
});
So the store.getActions()
returns setError
from catch
block, why is that? It should return setList
from then
block. What am I doing wrong? response
variable returns mockList
just fine.
Edit
The error it returns is API not configured
, I'm using aws amplify.
fetchList
is called when the component is mounted, mocked API.get
doesn't affect the first time it's called, and second call doesn't do anything. It's a bad practice to mock methods by assigning a spy to them because they cannot be restored after a test.
The problem with fetchList
is that it cannot be spied or mocked because it's used in the same module it's defined. The promise it creates in useEffect
cannot be chained, promises need to be flushed in order to avoid race condition.
It can be:
let flushPromises = () => new Promise(resolve => setImmediate(resolve));
jest.spyOn(API, 'get').mockResolvedValue({ data: mockList });
const wrapper = mount(
<Provider store={store}>
<List />
</Provider>
);
await flushPromises();
expect(store.getActions())...