0
votes

I am currently unit testing my NestJS Service. My entity is called 'User' and I established a basic Service that allows me to interact with a MS SQL server, with GET and POST endpoints established in my Controller.

I have a delete method in my Controller file that basically just calls the delete method from my Service:

@Injectable()
export class ServiceName {
  constructor(@InjectEntityManager() private manager: EntityManager) {}


  async delete(id: number): Promise<any> {
    return await this.manager.delete(User, id);
  }
// some other functions 

To test the delete method of my Controller, I mock the same method from the Service. However, when I defined a clear mock return value for the delete method from the service, this mocked return value does not match the return value from the delete method from the Controller, although they should be the same.

Here are my configurations in my spec.ts file:

    const mockService = {
        delete: jest.fn(),
    };

    beforeEach(async () => { 
        const module: TestingModule = await Test.createTestingModule({
            controllers: [ControllerName],
            providers: [ServiceName],
        })
            .overrideProvider(ServiceName)
            .useValue(mockService) 
            .compile();

        service = module.get<ServiceName>(ServiceName);
        controller = module.get<ControllerName>(ControllerName);
    });

Here's the test case in my spec.ts file:

        it('testing delete', async () => {
            mockService.delete.mockReturnValue(5);
            expect(controller.delete(5)).toEqual(5);
        }) 

The above test case fails, and below is shown the error message:

    expect(received).toEqual(expected) // deep equality

    Expected: 5
    Received: {}

      122 |         it('testing delete', async () => {
      123 |             mockService.delete.mockReturnValue(5);
    > 124 |             expect(controller.delete(5)).toEqual(5);
          |                                          ^
      125 |         })
      126 |     });
      127 | });

Any help is greatly appreciated!

1
show us your controller.delete method - Micael Levi
btw serviceName.delete is async thus you need to use .mockResolvedValue and use await on controller.delete return - Micael Levi
It worked! For some reason, using .mockResolvedValue made the test pass. Thank you so much Michael! - Etfrerrr

1 Answers

1
votes

As a heads up, while you can pass the provider directly, I would suggest providing a mock of the provider in your unit tests. So instead of having providers: [ServiceName] you would have

{
  provide: ServiceName,
  useValue: {
    delete: jest.fn().mockResolvedValue(5)
  }
}

This way you know everything being used right from the test. Also, this pattern will keep you from running into problems when a provider has it's own dependencies which might or might not need to be mocked. For more examples you can check out my testing repo