Tests not work when use Timer Mocks like `jest.useFakeTimers()`
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 63.2k
- Forks
- 10.3k
- Avg merge
- 11d 20h
- Merged PRs (30d)
- 2
Description
Hello, when I use jest.useFakeTimers(), I don't know how long I have to advance the timers or what method to call so that the internal code that sends and receives socket.io events will be executed
I want to know what I should do, because I want to increase the execution time of the tests, and since I have to write tests for some features that use setTimeouts, and some RxJs methods like debounce, throttle, this is essential for me.
This is a minimal example of jest with typescript.
jest.useRealTimers();
const {createServer} = require('http');
import {Server, Socket} from 'socket.io';
import {Socket as ClientSocket, io as ioc} from 'socket.io-client';
describe('my awesome project', () => {
let io: Server;
let serverSocket: Socket;
let clientSocket: ClientSocket;
beforeAll(done => {
const httpServer = createServer();
io = new Server(httpServer);
httpServer.listen(() => {
const port = httpServer.address().port;
clientSocket = ioc(`http://localhost:${port}`);
io.on('connection', socket => {
serverSocket = socket;
});
clientSocket.on('connect', done);
});
});
afterAll(() => {
jest.useRealTimers();
io.close();
clientSocket.close();
});
test('should work', async () => {
jest.useFakeTimers();
const onHello = jest.fn();
clientSocket.on('hello', onHello);
serverSocket.emit('hello', 'world');
jest.advanceTimersByTime(10000);
jest.runAllTicks();
await new Promise(jest.requireActual('timers').setImmediate);
expect(onHello).toBeCalledTimes(1);
// Error
// Expected number of calls: 1
// Received number of calls: 0
});
});
And this is the way how I write test currently without Timer Mocks, but I need to await a setTimeout promise with N milliseconds, to make it work, the problem is this time is variable, for example if I set 4 milliseconds, sometimes the test pass and other times fail, I think is based on my pc resources and the amount of tests that are running.
But without fake timers this increment the total execution time, and I can't calculate how long to wait for when I want to wait for other methods to execute, for example from rxjs debounceTime or throttleTime
jest.useRealTimers();
const {createServer} = require('http');
import {Server, Socket} from 'socket.io';
import {Socket as ClientSocket, io as ioc} from 'socket.io-client';
describe('my awesome project', () => {
let io: Server;
let serverSocket: Socket;
let clientSocket: ClientSocket;
beforeAll(done => {
const httpServer = createServer();
io = new Server(httpServer);
httpServer.listen(() => {
const port = httpServer.address().port;
clientSocket = ioc(`http://localhost:${port}`);
io.on('connection', socket => {
serverSocket = socket;
});
clientSocket.on('connect', done);
});
});
afterAll(() => {
io.close();
clientSocket.close();
});
test('should work', async () => {
const onHello = jest.fn();
clientSocket.on('hello', onHello);
serverSocket.emit('hello', 'world');
await sleep(4);
// sometimes pass and sometimes fail
// with 4 milliseconds because this time is not enough time.
//
// So how many time should I wait?
//
// But without fake timers this increment total execution time,
// and I can't calculate how long to wait for
// when I want to wait for other methods to execute,
// for example from rxjs debounceTime or throttleTime
expect(onHello).toBeCalledTimes(1);
});
});
function sleep(ms: number) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
Thank you
"socket.io": "^4.5.3",
"socket.io-client": "^4.5.4"
"jest": "^29.2.2",
Platform:
- Node: v16.13.1
- OS: Windows 10
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the minimal Jest TypeScript example in the issue and trace the socket.io server/client event flow together with Jest fake timers. Determine what test behavior or documentation should change, and validate the result against the shown serverSocket.emit('hello', 'world') case and its expected callback count.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nodejs, typescript
- Domain
- backend-api-design, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100