etiennnr
etiennnr

Reputation: 314

unit testing - jest with supertest gives a timeout

I got an error running my unit tests. I am using a express app from NodeJS. I want to test the return message (200) and (eventually) the output of a function.

const {Router} = require('express');
const {query} = require('../dbConfig');

module.exports = (router = new Router()) => {
    //get only one user from the id
    router.post('/getUser', async (req,res)=>{
        id = req.body.id;
        sql = "SELECT lastname, firstname, email, title_id, id, state FROM users WHERE id=" + id;
        let result = await query(sql);
        if(result.length >= 1){
            res.send(result[0]);
        }

    })
    return router;
};

But when I try to run the following test :

const app = require('../../app')
const request = require('supertest')
jest.mock('../../dbConfig');;

describe('POST /getUser', () => {
    let data = {
        id:1
    }

    it('Response 200 + response type',(done)=>{
        request.agent(app)
            .post('/getUser')
            .send(data)
            .expect(200, done)
    })
});

It returns me the following error

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

I tried diffrent variations without success... I also tried the doc online which wasn't really helpful for this error... I run jest with npx jest and the mock file looks like this :

const rep={
    "lastname": "admin",
    "firstname": "admin",
    "email": "[email protected]",
    "title_id": 1,
    "id": 1,
    "state": 1
};


const query = (sqli) =>{
    return new Promise((resolve, reject) =>{
        console.log("SQL request : " + sqli)
        if(sqli === "SELECT lastname, firstname, email, title_id, id, state FROM users WHERE id=1"){
            console.log("Passed")
            resolve(rep);
        }
    });

}

module.exports = {query};

Upvotes: 2

Views: 5016

Answers (2)

J. Maria
J. Maria

Reputation: 416

Your query method returns an object (rep), and you check the length of it in the POST handler. The length of an object is undefined, so it doesn't reach the res.send. You need to set an else option with another res.send so it answers the client no matter what happens. Also, you probably want to change that if in the POST handler, or the format of the return in the mock file.

For instance, in your Mock file:

const query = (sqli) =>{
    return new Promise((resolve, reject) =>{
        console.log("SQL request : " + sqli)
        if(sqli === "SELECT lastname, firstname, email, title_id, id, state FROM users WHERE id=1"){
            console.log("Passed")
            resolve([rep]); //Now it's an array of length 1, reaches the first send
        } else {
            reject([]); //Length is 0, so it will reach the second send
        }
    });

}

Controller

if(result.length >= 1){
    res.send(result[0]);
} else {
    res.status(500).send('Something broke!');
}

Upvotes: 1

iagowp
iagowp

Reputation: 2494

Are you sure your db is initialized? Can you try this at your controller?

router.post('/getUser', async (req,res)=>{
    id = req.body.id;
    sql = "SELECT lastname, firstname, email, title_id, id, state FROM users WHERE id=" + id;
    try {
       let result = await query(sql);
       if(result.length >= 1){
           res.send(result[0]);
       } else {
           res.sendStatus(404);
       }
    } catch(err) {
       res.sendStatus(500)
    }

})

In case your db isnt correctly initialized, or if query throws an error, it will never respond

Upvotes: 1

Related Questions