javascriptexpressjestjssupertest

Test API with URL Params in JEST


There is an API endpoint that needs integration tests using Jest.

Here's the endpoint: http://localhost/universities/ucla/class/2013/studentalis/johndoe. The request is a put request and it returns 201 on Postman.

However, when I test it:

const express = require("express");
const request = require("supertest");
const updateStudentRoute= require('../handlers/updateStudent');
const app = express();
app.use(express.json());
app.use('/universities/ucla/class/2013/studentalis/johndoe', updateStudentRoute);
describe('Update Student Details in Databse', () => {
    it('Update Student Details in Database', async() => {
        const updateStudentRequestBody = require('./updateStudentRequestBody');
        const response = await request(app).put(`universities/ucla/class/2013/studentalis/johndoe`)
                                           .send(createInstanceRequestBody);
        expect(response.statusCode).toBe(201);
    });
});

The test returns timeout because it got an error in the updateStudent.js file. In it, it is not able to parse the url params:

function getQuery(req, studentid, id) {
  return {
    universityName: req.params.universityName.toString(),
    class: req.params.class.toString(),
    studentAlias: req.params.studentAlias.toString()
  };
}

TypeError: Cannot read properties of undefined (reading 'toString')

  226 |   return {                                                                                                                                                                                                                                                 
> 227 |     universityName: req.params.universityName.toString(),                                                                                                                                                                                                  
      |                                               ^
  228 |     class: req.params.class.toString(),
  229 |     studentAlias: req.params.studentAlias.toString()

When I debugged, req is an object and req.params is empty, thus req.params.universityName.toString() is undefined. So my guess is that the way I set the url params is incorrect. Any leads on what the syntax would be?


Solution

  • Definitely req.params will be empty because you don't specified any route parameters.

    Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the req.params object, with the name of the route parameter specified in the path as their respective keys.

    Let see how to define, In your server.js or index.js simply specify the route parameters in the path of the route as shown below. For ex: /path/:name here name is the route parameter

    const express = require("express");
    const updateStudentRoute= require('../handlers/updateStudent');
    const app = express();
    app.use(express.json());
    // use put method instead use
    app.put('/university/:universityName/class/:class/studentalias/:studentAlias', updateStudentRoute);
    
    app.listen(2000,function(){  
       console.log("Server is running on port 2000");  
    });
    

    One more thing you are using app.use instead use app.put because app.use() is intended for binding middleware to your application.

    So far you will have an idea about route parameters. Let see how to test them

    In your test js

    const supertest = require("supertest");
    const request = supertest("http://localhost:2000");
    
    describe('Update Student Details in Databse', () => {
        it('Update Student Details in Database', async() => {
            // const updateStudentRequestBody = require('./updateStudentRequestBody'); put method does not have body
            const response = await request.put(`/university/ucla/class/2013/studentalias/johndoe`); // here you can use the values in place of :name
            expect(response.statusCode).toBe(201);
        });
    });
    

    Passing the app instance each time is not necessary, if you're testing the same host you may simply re-assign the request variable with the initialization url, a new Test is created per request.VERB() call.

    Finally don't forget to send the response code 201, because by default express answer all endpoints with 200