Search code examples
node.jsexpressjestjssupertestdotenv

Environment variable not available in a route while using NodeJS + Express and testing with Jest + Supertest


I am using dotenv to load an environment variable which is intended to be an API Token. All requests made to this API are valid only if they carry this token in a header.

I've already tried using:

require("dotenv").config();

in my app.js file and also wrote my start script as:

"start": "node -r dotenv/config ./bin/www"

being the two recommended ways to load the environment variables in a .env file.

Using both approaches, my API_TOKEN environment variable is available at app.js, as expected.

I am using Jest for testing, although I prefer Mocha and always use it. Saying this is relevant for people to understand why I am not sure my problem is due to Jest or not.

I have this test:

test("POST /cpf/* should fail when authorization token is wrong", async() => {
    const data = { cpf: "927.059.107-78" };

    await supertest(app)
    .post("/cpf/verify")
    .set("authorization","c68d357aaaaa8d82a29bade16ece0a1e")
    .send(data)
    .expect(500)
    .then(async (response) => {
        expect(response.body.mensagem).toBe("Request not authorized => invalid token.")
    })

});

and this test is specific to this middleware:

router.use(function (req, res, next) {
    let { authorization } = req.headers;
    if (authorization !== process.env.API_TOKEN) {
        res.status(500).send({ mensagem: "Requisição não autorizada => token de autorização inválido." });
    }
    next();
});

As you may see, it should block all requests when the authorization token is different from the one stored in my .env file.

It happens that process.env.API_TOKEN is undefined, but it shouldn't be!

I run out of ideas about this. Any suggestions?


Solution

  • The point here wasn't Jest at all, but my directory structure.

    I was using a structure like this:

    project_home/
      |
      |-- node modules      (only with Jest and Supertest)
      |-- package.json      (only with Jest and Supertest)
      |-- package-lock.json (only with Jest and Supertest)
      |-- __tests__/        (directory with the Jest test suites)
      |-- api               (Express application)
           |
           |-- Dockerfile
           |-- node modules        (all app dependencies)
           |-- package.json        (all app dependencies)
           |-- package-lock.json   (all app dependencies)
           |-- .env                (environment variables)
           |-- app.js              (app main file)
           |-- routes/             (routes directory)
    

    My idea, when I did this, was isolating the tests and dockerizing only the app, without the test's code. It doesn't work this way, as I found out.

    When I moved the __tests__ directory to the api directory, all the environment variable got accessible immediately to my test cases.

    project_home/
      |
      |-- api                      (Express application)
           |
           |-- __tests__/          (directory with the Jest test suites)
           |-- Dockerfile
           |-- node modules        (all app dependencies)
           |-- package.json        (all app dependencies)
           |-- package-lock.json   (all app dependencies)
           |-- .env                (environment variables)
           |-- app.js              (app main file)
           |-- routes/             (routes directory)
    

    As a bonus, I could remove the files package.json, package-lock.json and the directory node modules in my project_home directory, since they are not needed anymore. I just had to use:

    npm i jest --save-dev
    

    and

    npm i supertest --save-dev
    

    inside my api directory.