76

I have written test cases for signin API using jest. After completing all five test of a test suit jest give me following error in log.

Can any body tell Why it is So and how to fix it?

CODE:(signup.test.ts)

import request from 'supertest';
import { TYPES } from '../src/inversify.types'
import { Application } from '../src/app/Application'
import { container } from '../src/inversify.config'
import dotenv from 'dotenv'
import { RESPONSE_CODE } from '../src/utils/enums/ResponseCode'
import { RESPONSE_MESSAGES } from '../src/utils/enums/ResponseMessages'
import { UserSchema } from '../src/components/user/User';
// import jwt from 'jsonwebtoken';
var application: Application

describe("POST / - SIGNUP endpoint", () => {
    // var testusers: any;
    //This hook is executed before running all test cases, It will make application instance, make it to listen 
    // on it on port 3000 and add test document in DB
    beforeAll(async () => {
        // Make enviroment variables available throughout the application
        dotenv.config();
        // Getting application instance using iversify container
        application = container.get<Application>(TYPES.Application);
        // Initialize frontside of application
        await application.bootstrap();
        // Starting Application server on given port
        await application.listen(3000);
    });

    afterAll(
        //This hook is executed after running all test cases and delete test document in database
        async () =>{
        const res = await UserSchema.deleteMany({ Name: { $in: [ "Test User", "Test" ] } });
        // `0` if no docs matched the filter, number of docs deleted otherwise
        console.log('---------------------->>>>>>>>>>>>>>>>>>>', (res as any).deletedCount);
    }
    )

    it("Signup for user that don\'t exists", async () => {
        const response = await request(application.getServer()).post('/user/signup')
        .send({
            "Email": JSON.parse(process.env.TEST_USER).Email,
            "Name": "Test User",
            "Password": process.env.TEST_ACCOUNTS_PASSWORD
            })
            expect(response.status).toBe(RESPONSE_CODE.CREATED);
            expect(JSON.parse(response.text)).toEqual(expect.objectContaining({ 
                Message: RESPONSE_MESSAGES.ADDED_SUCESSFULLY, 
                Data: expect.objectContaining({
                    Name: 'Test User',
                    Country: '',
                    PhoneNumber: '',
                    // Password: '$2b$10$nIHLW/SA73XLHoIcND27iuODFAArOvpch6FL/eikKT78qbShAl6ry',
                    Dob: '',
                    Role: 'MEMBER',
                    IsEmailVerified: false,
                    IsBlocked: 'ACTIVE',
                    IsTokenSent: false,
                    twoFAStatus: false,
                    // _id: '5c812e2715e0711b98260fee',
                    Email: JSON.parse(process.env.TEST_USER).Email
                })
            })
            );
        console.log('*** Signup for user that don\'t exists *** response', response.text, 'response status', response.status);   
    });
    it("Signup for user that exists", async () => {
        const response = await request(application.getServer()).post('/user/signup')
        .send({
            "Email": JSON.parse(process.env.TEST_USER).Email,
            "Name": "Test User",
            "Password": process.env.TEST_ACCOUNTS_PASSWORD
            })
            expect(response.status).toBe(RESPONSE_CODE.CONFLICT);
            expect(JSON.parse(response.text)).toEqual({ 
                Message: RESPONSE_MESSAGES.ALREADY_EXISTS
            })
        console.log('*** Signup for user that don\'t exists *** response', response.text, 'response status', response.status);   
    });

});

Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with --detectOpenHandles to troubleshoot this issue.

Cannot log after tests are done. Did you forget to wait for something async in your test?

Attempted to log "{ accepted: [ '[email protected]' ],
      rejected: [],
      envelopeTime: 621,
      messageTime: 867,
      messageSize: 906,
      response: '250 2.0.0 OK  1551945300 f6sm5442066wrt.87 - gsmtp',
      envelope:
       { from: '[email protected]',
         to: [ '[email protected]' ] },
      messageId: '<[email protected]>' }".




at CustomConsole.log (node_modules/jest-util/build/CustomConsole.js:156:10)
  at src/email/MailHandler.ts:2599:17
  at transporter.send.args (node_modules/nodemailer/lib/mailer/index.js:226:21)
  at connection.send (node_modules/nodemailer/lib/smtp-transport/index.js:247:32)
  at callback (node_modules/nodemailer/lib/smtp-connection/index.js:435:13)
  at stream._createSendStream (node_modules/nodemailer/lib/smtp-connection/index.js:458:24)
  at SMTPConnection._actionSMTPStream (node_modules/nodemailer/lib/smtp-connection/index.js:1481:20)
  at SMTPConnection._responseActions.push.str (node_modules/nodemailer/lib/smtp-connection/index.js:968:22)
  at SMTPConnection._processResponse (node_modules/nodemailer/lib/smtp-connection/index.js:764:20)
  at SMTPConnection._onData (node_modules/nodemailer/lib/smtp-connection/index.js:570:14)
3
  • 1
    Can you post the code for the test itself? It will help to diagnose what is happening. Here is a Jest async example and an example GitHub issue to give you some idea of things that can cause this type of error. Commented Mar 8, 2019 at 4:37
  • @ty2k. I have updated the code plz check. I have already checkout out docs but unable to figure out Commented Mar 8, 2019 at 6:56
  • 1
    Check out the Callbacks section in Jest's async documentation, specifically the section that passes done as an argument. There's also this post in a Supertest issue that has the same sort of problem as you. Basically, your tests are completing before your server is shut down. Commented Mar 8, 2019 at 18:17

11 Answers 11

17

I was using the react-native default test case (see below) when Cannot log after tests are done happened.

it('renders correctly', () => {
  renderer.create(<App />);
});

Apparently, the problem was that the test ended but logging was still needed. So I tried to make the callback in the test case async, hoping that the test won't terminate immediately:

it('renders correctly', async () => {
  renderer.create(<App />);
});

And it worked. However, I have very little clue what the inner working is.

Sign up to request clarification or add additional context in comments.

1 Comment

Sadly not works for me! Note: In App.js I just render Navigation component Config "NavigationContainer"
15

If you are using async/await type in your code, then this error can occur when you are calling async function without await keyword.

In my case, I have defined a function like this below,

async getStatistics(headers) {
    ....
    ....
    return response;
}

But I have called this method like getStatistics(headers) instead of await getStatistics(headers).

When I included await, it worked fine and the issue resolved.

Comments

9

In my case while using nodejs + jest + supertest the problem was that when I import app from "./app" to my test file to do some stuff with supertest (request(app)), I actually import with app.listen() , because when I'm exporting app, export takes in account app.listen() too, but we don't need app.listen() in tests and it throws an error

"Cannot log after tests are done.Did you forget to wait for something async in your test?"

Here is all in one file(that's the problem!)

const app = express();

app.use(express.json());

// ROUTES
app.get("/api", (req, res) => {
    res.json({ message: "Welcome to Blog API!" });
});

app.use("/api/users", usersRoutes);
app.use("/api/blogs", blogsRouter);

// The server will start only if the connection to database is established
mongoose
    .connect(process.env.MONGO_URI!)
    .then(() => {
        console.log("MongoDB est connecté");

        const port = process.env.PORT || 4000;
        app.listen(port, () => console.log(`The server is running on port: ${port}`));
    })
    .catch(err => {
        console.log(err);
    });

export default app;

To solve this issue I created 2 separate folders:

// 1) app.ts

Where I put all stuff for my const app = express(), routes etc and export app

dotenv.config();

const app = express();

app.use(express.json());

// ROUTES
app.get("/api", (req, res) => {
    res.json({ message: "Welcome to Blog API!" });
});

app.use("/api/users", usersRoutes);
app.use("/api/blogs", blogsRouter);

export default app;

// 2) index.ts

Where I put app.listen() and mongoose.connection() and import app

import mongoose from "mongoose";
import app from "./app";

// The server will start only if the connection to database is established

mongoose
    .connect(process.env.MONGO_URI!)
    .then(() => {
        console.log("MongoDB est connecté");

        const port = process.env.PORT || 4000;
        app.listen(port, () => console.log(`The server is running on port: ${port}`));
    })
    .catch(err => {
        console.log(err);
    });

1 Comment

link. at the 32 minute he explain the problem
3

For me I needed to add an await before the expect() call also to stop this error (and an async before the test() callback function).

Also caused and fixed Jest not detecting coverage on the lines in the code throwing the error!

test("expect error to be thrown for incorrect request", async () => {
  await expect(
  // ^ added this
    async () => await getData("i-made-this-up")
  ).rejects.toThrow(
    "[API] Not recognised: i-made-this-up"
  );
});

getData() returns an Axios call and in this case an error is caught by catch and re-thrown.

const getData = async (id) => {
  return await axios
    .get(`https://api.com/some/path?id=${id}`)
    .then((response) => response.data)
    .catch((error) => {
      if (error?.response?.data?.message) {
        console.error(error) // Triggered the error
        throw new Error("[API] " + error.response.data.message);
      }

      throw error;
    });
};

Comments

3

This happened to me because I had an infinite loop while (true). In my case, I was able to add a method for setting the value of the loop based on user input, rather than defaulting to true.

Comments

2

I solved it with the env variables:

if (process.env.NODE_ENV !== 'test') {
  db.init().then(() => {
    app.listen(PORT, () => {
      console.log('API lista por el puerto ', PORT)
    })
  }).catch((err) => {
    console.error(err)
    process.exit(1)
  })
} else {
  module.export = app
}

Comments

1

In my case, the error was caused by asynchronous Redis connection still online. Just added afterall method to quit Redis and could see the log again.

Working on Typescript 4.4.2:

test("My Test", done => {
    let redisUtil: RedisUtil = new RedisUtil();
    let redisClient: Redis = redisUtil.redis_client();
    done();
});

afterAll(() => {
    redisClient.quit();
});

Comments

1

Also don't forget to extend your timeout if you have a long running test using

jest.setTimeout();

In my case I'm paging through API calls and logging so it will extend after jest's default timeout, which is why I was getting the error.

Comments

0

I had a similar issue:

Cannot log after tests are done. Did you forget to wait for something async in your test?
Attempted to log "Warning: You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ".

It was due to a missing static keyword. This code caused the issue:

class MyComponent extends React.Component<Props, State> {
  propTypes = {
    onDestroy: PropTypes.func,
  }
}

It should have been:

class MyComponent extends React.Component<Props, State> {
  static propTypes = {
    onDestroy: PropTypes.func,
  }
}

1 Comment

an explanation of why this worked would be helpful
0

I faced same warnings. However the fix is bit weird:

The jest unit test script import a function (which is not export from src/). After I added the export to the function to be tested. The error disappears.

Comments

0

In my case I had to just increase the default timeout for it function

it("Your tests", async () => {
    // your tests  
}, 100000);

I also had a somewhat slightly noticeable timeout error above the Cannot log after tests are done. errors:

thrown: "Exceeded timeout of 5000 ms for a test.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.