2

I have a service in NestJS I'm testing using @nestjs/testing in Typescript. But one of the methods depends on another, I would like to mock out the dependent method for only one test, so I can't use the ES6 class mocking, as that would override the class I'm testing with a mock.

class UsersService {
  findMany(ids) {
    return ids.map(id => this.findOne(id));
  }
  
  findOne(id) {
    return this.httpService.get(id);
  }
}

I want to test both methods, but I want to mock findOne only when I'm testing findMany.
Thanks in advance.

C0l0red
  • 35
  • 1
  • 7
  • 1
    _Don't._. Don't mock parts of the thing you're supposed to be testing. See e.g. https://stackoverflow.com/q/66738500/3001761. – jonrsharpe Jan 16 '22 at 22:13

1 Answers1

2

You want to use spying here. Look for 'spyOn' in this documentation: https://docs.nestjs.com/fundamentals/testing near the bottom.

Here's an example I tried to cook up that's related to your posted code:

test('findMany', () => {
  const spy = new UsersService;
  // Here's the key part ... you could replace that "awesome" with something appropriate
  jest
    .spyOn(spy, 'findOne')
    .mockImplementation(() => "awesome");
  
  // Just proving that the mocking worked, you can remove this
  expect(spy.findOne()).toBe("awesome");

  const ids = ["Dio", "Lemmy"];
  expect(spy.findMany(ids)).toStrictEqual(["awesome", "awesome"])
});

Joe Vienneau
  • 66
  • 1
  • 5
  • 1
    Thanks, man. Worked like a charm. Can't believe I didn't think about it. – C0l0red Jan 17 '22 at 11:02
  • The cool thing is it works with imported/required packages too! so you can do `const spy = require('tmp-promise'); jest.spyOn(spy, 'fileSync').mockImplementation(() => ({ name: 'test_file_name' }));` so now any method call that runs `tmp.fileSync()` will return `{ name: 'test_file_name' }`. This is necessary as the value being returned otherwise is random so tests are undeterministic. – Ayudh Feb 07 '23 at 10:21