1

I'm trying to learn how to unit test for a particular task. Here are some of my files:

//examples.service.ts
export class ExamplesService {
  constructor(
    @InjectModel(Example.name) private ExampleModel: Model<Example>,
    private readonly someService: SomeService,
    private readonly someOtherService: SomeOtherService
  ){}

  async findAll(): Promise<Example[]> { 
    return this.exampleModel.find().exec();
  }

  //... other class methods
}
//examples.controller.ts
@Controller('examples')
export class ExamplesController {
  constructor(private readonly examplesService: ExamplesService) {}
    
    @Get()
    async findAll(): Promise<Example[]> {
      return this.examplesService.findAll();
    }
    //... 

How can i test the functions in examples.service.ts, if it requires me to create a new ExamplesService object that also needs SomeService and SomeOtherService params? Do I create a mock of all of these objects? If so, how?

This is what I have so far:

//examples.controller.spec.ts
jest.mock('./examples.service');
describe(ExamplesController, ()=> {
  let examplesController: ExamplesController;
  let examplesService: ExamplesService;

  beforeEach(async () => {
    const module = TestingModule = await Test.createTestingModule({
      controllers: [ExamplesController],
      providers: [ExamplesService],
    }).compile();
  
    examplesController = module.get<ExamplesController>(ExamplesController)
    examplesService = module.get<ExamplesService>(ExamplesService)
  })
  
  describe('findAll', () => {
    it('should return all the examples', async () => {
      let examples = await examplesService.findAll();
      expect(examples).resolves.toEqual('some result');
    })
  });
})

However, when testing findAll, it is unsuccessful because examples always equals to undefined.

Thank you!

Cris
  • 209
  • 2
  • 10

1 Answers1

1

You need to mock all your dependencies. There are different ways to mock classes. There's some good examples at jest's website https://jestjs.io/docs/en/es6-class-mocks. Not sure what you want to test but can do something like following

    jest.mock('./Model');
    const someService = {
            someMethod: jest.fn().mockReturnValue(Math.random()),
            someOtherMethod: jest.fn().mockReturnValue({ }),
     };
    
    const someOtherService = {
          someMethod: jest.fn().mockReturnValue(Math.random()),
           
    };
       
    
    const examplesService = new ExamplesService(exampleModel as any, someService as any, someOtherService as any);
web2dev
  • 557
  • 10
  • 28
  • Thank you! I have a question: why only mock the model, and not someService and someOtherService too? Also I am trying to test the functions in ExampleService, e.g. findAll() returns the correct values – Cris Feb 01 '21 at 14:26
  • As you can see we are not creating new object for someService and someOtherService . We are mocking 2 methods of someService and then in the ExampleService mocking someService as any. Same applied for someOtherService. There are different ways of mocking a dependency. I have just shown 2 types. – web2dev Feb 01 '21 at 22:22
  • In your test you are mocking the test class. I think you need to create objects for the test class and mock other dependencies. But I could be wrong. There's a similar qs answered here: https://stackoverflow.com/questions/52878055/how-to-unit-test-controller-and-mock-injectmodel-in-the-service-constructor/52913940 – web2dev Feb 01 '21 at 22:25