What is the easiest way to test event listeners in jest?

17,327

The issue is that calling await on xyz.getVal doesn't actually do anything since getVal is a synchronous function that just sets up the event listeners...

...so the asynchronous events haven't finished processing by the time the expect runs and fails.


It looks like you've already got a spy on test.on.

Instead of mocking its implementation, just use it to get the callback function.

Then you can call and await the callback function directly:

  // in beforeEach
  mockData = [an array containing 10 values]
  onSpy = jest.fn();

it('should trigger callback once per message', async () => {
  xyz.getVal(process);
  const callback = onSpy.mock.calls[0][1];  // <= get the callback (second argument of the first call to test.on)
  await callback(mockData);  // <= call and await the callback directly
  expect(process).toHaveBeenCalledTimes(10);  // Success!
});
Share:
17,327
user2821242
Author by

user2821242

Updated on June 04, 2022

Comments

  • user2821242
    user2821242 almost 2 years

    I'm trying to test the below function

     getVal(process) {
        test.on('data', async data => {
        try {
           for (const val of data) {
           await process(val);
           console.log('processed')
        }} catch (e) {}
        });
        test.on('error', err => {
           console.log('error', err)
         });
        }
    
    process(payload) {
    return new Promise(resolve=>{.....})
    };
    

    Jest test: // in beforeEach

    mockData =[an array containing 10 values] 
        onSpy = jest
              .fn()
              .mockImplementationOnce(async (data, callback) => {
                callback(mockData);
              })
              .mockImplementationOnce((error, callback) => {
                callback(mockErr);
              });
    
     it('should trigger callback once per message', async () => {
        await xyz.getVal(process);
        await expect(process).toHaveBeenCalledTimes(10);
     });
    

    I expect the process() to be called 10 times since the data is sent 10 times. However it's called only 2 times when I assert but when I put a console.log in the function itself and run the test, that gets called 10 times.

    I'm not sure what's wrong. Appreciate any help.