user2821242
user2821242

Reputation: 1181

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

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.

Upvotes: 5

Views: 31846

Answers (1)

Brian Adams
Brian Adams

Reputation: 45810

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!
});

Upvotes: 8

Related Questions