Reputation: 650
I have a controller for simple car buying/selling API which does this
async processCarSale(@Res() res: any) {
if(carSaleService.sale()) {
return res.status(201).send(<some-body>);
}
return res.status(204).send(<some-other-body>);
}
I am trying to test that the status code is set correct with a unit test. Googling and using SO I found example similar to this
const mockResponse = {
status: jest.fn(),
send: jest.fn()
}
const mockResponseSent = { send: jest.fn() };
mockResponse.status = jest.fn(() => mockResponseSent);
await carController.processCarSale(response);
expect(response.statusCode).toBe(200);
However this does not seem to actually test the status code.
Is there any way to test the statusCode sent in the response via Express?
Upvotes: 0
Views: 3171
Reputation: 1999
You can achieve this by using supertest (provided by default with Nestjs).
You can use the also provided HttpStatus enum which provides all HTTP code status.
test('/route (POST)', () => {
const data = { any: 'data', what: 'you want' }
request(app.getHttpServer())
.post('/route')
.send(data)
.expect(HttpStatus.CREATED)
.expect('Content-Type', /json/)
}
Upvotes: 1
Reputation: 70061
Your mock doesn't ever set a value called statusCode
, it just stubs the functionality and returns the same object so that send()
can be called as well (also a stub). If you want to be able to test something like res.statusCode === 200
you could do something like this:
const mockResponse = {
status: jest.fn(),
send: jest.fn(),
statusCode: 0
}
const mockResponseSent = { send: jest.fn() };
mockResponse.status = jest.fn(() => {
mockResponseSent.statusCode = 200;
return mockResponseSent;
});
await carController.processCarSale(response);
expect(response.statusCode).toBe(200);
However, this is essentially jsut re-writing the logic of your controller in the first place, which isn't really good. So what would be better would be to take advanatage of Jest's mockImplementation()
method where you can do
const mockResponse = {
status: jest.fn(),
send: jest.fn()
}
const mockResponseSent = { send: jest.fn() };
mockResponse.status = jest.fn().mockImplementation((status) => {
mockResponseSent.statusCode = status;
return mockResponseSent;
});
await carController.processCarSale(response);
expect(response.statusCode).toBe(200);
Overall, though, I would suggest ditching the use of res
in your controller and suggest letting Nest handle the setting of the http status code and sending the response. You can set the code to something other than default by using @HttpCode()
Upvotes: 2