I'm trying write a test for a simple polling function that checks an API endpoint until it gets a 200 OK
response and retries on any 400
or 500
response up to maxAttempts. I'm having trouble with the unit tests because the .then()
and .catch()
never seem to be executed regardless of the mock response.
The function I'm trying to test.
const waitForSsl = ({
onSuccess,
onFailure,
interval = 3,
maxAttempts = 10,
}) => {
const pingInterval = interval * 1000; // in seconds
let attempts = 0;
// TODO Add CertController to Laravel API to support this call.
const ping = () => Axios.get('/status')
.then((res) => { return onSuccess(); })
.catch(() => {
if (attempts < maxAttempts) {
attempts += 1;
setTimeout(ping, pingInterval);
} else {
onFailure();
}
});
// Give server a chance to restart by waiting 5 seconds before starting pings.
setTimeout(ping, 5000);
};
I can verify the function does exactly what I expect in the wild but I'd like a unit test for my own peace of mind.
This is my first attempt using jest and sinon
it('Should only poll maxAttempts + 1 times', () => {
jest.useFakeTimers();
const onSuccessCallback = () => 'success!';
const onFailureCallback = () => 'failed';
const getStub = sinon.stub(Axios, 'get');
getStub.rejects();
ssl.waitForSsl({
onSuccess: onSuccessCallback,
onFailure: onFailureCallback,
maxAttempts: 1,
});
expect(setTimeout).toHaveBeenCalledTimes(2);
});
This test fails with the error Expected mock function to have been called two times, but it was called one time
I did find this post, but the project isn't using async/await (ES8) yet and just calling Promise.resolve() without await doesn't fix the issue.
I'm open to using, moxios, or jest.mock()
but I'm getting the feeling there is no way to test a resolved/rejected promise when used as a callBack in setTimeout
. A working unit test and explanation of how that mocking works would be an ideal answer.