Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing NestJS controller with request

My Controller function definition looks like that: async login(@Req() request, @Body() loginDto: LoginDto): Promise<any> {

How I could prepare/mockup Request to provide first argument of function from Jest test? Inside funciton I am setting headers using request.res.set. Should I somehow pass real Request object to function and then check if header is set or rather mockup whole Request object and check if set function was called?

like image 340
mgo Avatar asked Jul 19 '18 12:07

mgo


2 Answers

I managed to do that mocking requests and response using node-mocks-http library.

const req = mocks.createRequest()
req.res = mocks.createResponse()

and then passing this as an argument.

const data = await authController.login(req, loginDto)
expect(req.res.get('AccessToken')).toBe(token.accessToken)
like image 163
mgo Avatar answered Oct 20 '22 07:10

mgo


I followed a different approach and instead of using node-mocks-http library I used @golevelup/ts-jest, also, instead of testing if the function returns some value, like res.json() or res.status(), I checked if the function was called with the value I wanted to.

I borrowed this approach from Kent C. Dodds's testing workshop, take a look for similar ideas. Anyway, this is what I did in order to mock the Response dependency of my Controller's route:

  // cars.controller.spec.ts
  import { createMock } from '@golevelup/ts-jest';

  const mockResponseObject = () => {
    return createMock<Response>({
      json: jest.fn().mockReturnThis(),
      status: jest.fn().mockReturnThis(),
    });
  };


  ... ommited for brevity

  it('should return an array of Cars', async () => {
    const response = mockResponseObject();

    jest
      .spyOn(carsService, 'findAll')
      .mockImplementation(jest.fn().mockResolvedValueOnce(mockedCarsList));

    await carsController.getCars(response);

    expect(response.json).toHaveBeenCalledTimes(1);
    expect(response.json).toHaveBeenCalledWith({ cars: mockedCarsList });
    expect(response.status).toHaveBeenCalledTimes(1);
    expect(response.status).toHaveBeenCalledWith(200);
  });

And that's it, I think that the implementation details aren't that important but in any case I'll leave the link to the Github repo where you can find the whole project.

like image 31
sigfried Avatar answered Oct 20 '22 06:10

sigfried