nock: Timeout when using jest "useFakeTimers" functionality
What is the expected behavior?
When mocking timers in jest I would expect mocks to pass properly as those (to me) shouldn’t be related to network communication.
jest
.useFakeTimers('modern')
.setSystemTime(new Date('2020-01-01').getTime())
What is the actual behavior?
Test case hangs until the whole suite times out
Possible solution Make mocks not reliant on the passing time, or maybe provide a flag that would handle this behaviour differently?
How to reproduce the issue
import nock from 'nock'
import axios from 'axios'
jest
.useFakeTimers('modern')
.setSystemTime(new Date('2020-01-01').getTime())
describe('Test', () => {
const url = 'http://www.google.com'
beforeEach(() => nock(url).get('/').reply(201))
afterEach(() => expect(nock.isDone()).toEqual(true))
it('should pass this test', async () => {
const res = await axios(url)
expect(res.status).toEqual(201)
})
})
Remove fake timers and the test case passes
Does the bug have a test case?
Yes, provided above
Versions
| Software | Version(s) |
|---|---|
| Nock | v13.0.11 |
| Node | v14.16.0 |
| TypeScript | v3.9.7 |
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 27
- Comments: 25 (2 by maintainers)
If you’re still having issues, try adding both
nextTickandsetImmediateto the array, this is the only way it’d work for me.jest.useFakeTimers({ doNotFake: ['nextTick', 'setImmediate'] }).setSystemTime(new Date('2022-01-01'))I followed @chornos13 comment, started with the whole list into
doNotFake, and removed one by one elements. The setup which is working on my computer (my setup is jest and supertest) is:I don’t understand why Jest doesn’t offer a way to just change the date without mocking the universe…
https://github.com/testing-library/user-event/issues/833 might be your issue if you are using testing library user events. Took me forever to figure out but this eventually fixed it for me:
None of these worked for me
The same issue also appears in vitest (as they use the same timer, but the doNotFake property doesnt exist there). Solved it there by using the following config:
I’ve tried the recently added
doNotFakeoption (jest.useFakeTimers({ doNotFake: ['nextTick'] })) but it didn’t work for me. Has anyone had any success with that new option?This worked for me, thanks!
Using
setImmediate(jest.useFakeTimers({ doNotFake: ['setImmediate'] })) worked for me (I’m usingrequestfromsupertest)https://github.com/facebook/jest/issues/10221
I wrote a small function to fix this issue by extending
jest.useFakeTimersoptions with a newfakeoption.Usage
cc @NTag
yeah, that’s true, before I found this answer, I tried one by one to not fake this functionality
and found out to making fakeTimers working is to not faking “‘nextTick’, ‘setImmediate’” but I still don’t know what effect If I do that on my test 😓
Also broken with sinon.useFakeTimers. The first mocked calls works, but any subsequent call times out.
https://github.com/nock/nock/blob/3efd7382011a8d1ca084bfc4043a332a796a0618/lib/intercepted_request_router.js#L66-L69
Here, Jest’s modern fake timer completely locks the time including the tick, so the connect is never reached, and a
Jest.runAllTicksis enough.@imcotton for me it happened the moment I’ve tried to use those modern timers and function
setSystemTime. I believe it was first introduced in jest 26.Using legacy timer indeed resolves the issue in this test case but it doesn’t let you set global time so it doesn’t really help me.
Per docs:
By specifying
jest.useFakeTimers('legacy')(instead of defaultmodern) would mitigate the hanging for me.Quote from Jest blog post on v27 release [1]:
1: https://jestjs.io/blog/2021/05/25/jest-27
Instead of
it should be
Fantastic, this fixed it for me! I’m using
supertestalso.When an error was thrown inside an async route handler in my Express app, and I used
jest.useFakeTimers(), the error was not being reported and the test timed out. Your solution fixed it, and now errors are successfully thrown and reported without the test timing out.doNotFake: ['nextTick']had no effect, butdoNotFake: ['setImmediate']did the trick. Thanks so much!Recently I experienced this too. It seems like ~nock uses “greater than” to test if the current time has passed the defined delay time (0 if not set explicitly), and respond only when the test assessed true.~ As Jest’s modern version timer locks, nock will not respond.
Try to advance at somewhere: