Home > OS >  NestJS Jest spy a callback function
NestJS Jest spy a callback function

Time:02-25

So I have a class which has a function. Inside this function, I execute another function from a library's class object which has a callback function. Inside that callback function, there's a method that I need to spy into. Is there any way to do that? Here's the rough detail:

export class Consume {
  private readonly consumer: Consumer; // class from the library
  private readonly randomService: RandomService; // class that it's method I want to spy on

  constructor() {
    this.consumer = new Consumer();
    this.randomService = new RandomService();
  }

  consume(): void {
    this.consumer.consume(async data => {
      ...
      this.randomService.doSomething('withParam'); // I need to spy here on this method
      ...
    })
  }
}

I've tried mocking, but don't seem to work, here's what I have tried:

it('should do something', () => {
  const consumerSpy = jest.spyOn(consumer, 'consume');
  consumerSpy.mockImplementation(cb => {
    cb(['data1', 'data2'])
  }); // mocking the library's function
  const randomServiceSpy = jest.spyOn(randomService, 'doSomething')
  expect(randomServiceSpy).toBeCalledTimes(1); // Number of times called: 0 returned
});

and also this:

it('should do something', () => {
  jest.mock('path/to/consume-class', () => {
    consume: jest.fn()
  }); // mocking Consume's consume function

  consume.consume(); // calling consume function from Consume class above

  const randomServiceSpy = jest.spyOn(randomService, 'doSomething')
  expect(randomServiceSpy).toBeCalledTimes(1); // Number of times called: 0 returned
});

Any help would be appreciated! :)

CodePudding user response:

You can use install spy on Class.prototype.method via jest.spyOn().

E.g.

consume.ts:

import { Consumer } from './lib';
import { RandomService } from './random.service';

export class Consume {
  private readonly consumer: Consumer;
  private readonly randomService: RandomService;

  constructor() {
    this.consumer = new Consumer();
    this.randomService = new RandomService();
  }

  consume(): void {
    this.consumer.consume(async (data) => {
      this.randomService.doSomething('withParam');
    });
  }
}

lib.ts:

export class Consumer {
  consume(fn) {
    fn();
  }
}

random.service.ts:

export class RandomService {
  doSomething(param) {}
}

consume.test.ts:

import { Consume } from './consume';
import { Consumer } from './lib';
import { RandomService } from './random.service';

describe('71246273', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  test('should pass', () => {
    jest.spyOn(Consumer.prototype, 'consume').mockImplementation((fn) => fn());
    const doSomethingSpy = jest.spyOn(RandomService.prototype, 'doSomething');
    const consume = new Consume();
    consume.consume();
    expect(doSomethingSpy).toBeCalledWith('withParam');
  });
});

Test result:

 PASS  stackoverflow/71246273/consume.test.ts (8.765 s)
  71246273
    ✓ should pass (3 ms)

-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   90.91 |      100 |   83.33 |      90 |                   
 consume.ts        |     100 |      100 |     100 |     100 |                   
 lib.ts            |      50 |      100 |       0 |      50 | 3                 
 random.service.ts |     100 |      100 |     100 |     100 |                   
-------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.879 s
  • Related