Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Environment variables undefined in NextJS when running Jest

I have a simple NextJS project set up, and am having problems getting Jest to recognize my environment variables. I've followed the instructions on https://nextjs.org/docs/basic-features/environment-variables#test-environment-variables to the best of my abilities, but can't get it to work.

Here is a simplfied version of my problem.

// .env.test.local
MY_ENVIRONMENT_VARIABLE=my_value
// My function I want to test
export const getEnvironment = () => {
  const MY_ENVIRONMENT_VARIABLE = process.env.MY_ENVIRONMENT_VARIABLE;
  return MY_ENVIRONMENT_VARIABLE;
};
// My test
import { getEnvironment } from './getEnvironment';

describe('Get environment', () => {
  it('will have the correct environment variable', () => {
    const myEnvironmentVar = getEnvironment();
    const expectedEnv = "my_value";
    expect(myEnvironmentVar).toEqual(expectedEnv);
  });
});

I'm running jest with jest --watch. I can see that it gets environment test, but none of my own specified variables show up.

The test above fails with

Expected: "my_value"
Received: undefined

If any additional files have relevance, please comment and I'll add what I have.

like image 967
Per Enström Avatar asked Dec 13 '22 08:12

Per Enström


2 Answers

NextJS 12 with new compiler SWC

NextJS version 12 introduced a new compiler, SWC, written in Rust. Managing environment variables with this compiler is really easy and built in. The documentation at https://nextjs.org/docs/advanced-features/compiler#jest describes how to set up your Jest configuration:

// jest.config.js
const nextJest = require('next/jest');

// Providing the path to your Next.js app which will enable loading next.config.js and .env files
const createJestConfig = nextJest({ dir: './' });

// Any custom config you want to pass to Jest
const customJestConfig = {
  moduleDirectories: ['node_modules', __dirname]
};

// createJestConfig is exported in this way to ensure that next/jest can load the Next.js configuration, which is async
module.exports = createJestConfig(customJestConfig);

Here I've added a custom config for moduleDirectories since I had problems with absolute imports when running tests. Since my code resides in . I wanted to add '.' as a module directory. But due to an open bug in Jest you have to specify __dirname instead.

NextJS 11 and earlier

Since I asked this question, the documentation has been updated and provided a better answer than starting next fully before the tests.

https://nextjs.org/docs/basic-features/environment-variables#test-environment-variables

The proposed way of loading environment variables into your testing environment is to add a config file for jest, add a setup script, and in that script use NextJS included loadEnvConfig function.

The .env.test can be filled with dummy data and checked into your repo. As with normal environment variables, you can override them locally with a .env.test.local-file.

// jest.config.js
module.exports = {
  globalSetup: '<rootDir>/__test__/setupEnv.js'
}
// __test__/setupEnv.js
import { loadEnvConfig } from '@next/env'

export default async () => {
  const projectDir = process.cwd()
  loadEnvConfig(projectDir)
}
# .env.test
MY_ENVIRONMENT_VARIABLE="a-variable-for-testing"
like image 61
Per Enström Avatar answered Jan 01 '23 14:01

Per Enström


Next needs to have been instantiated before your test is run in order to have access to these environment variables.

    // include this in your Jest setup file, or before your tests
    import next from "next";
    next({});

There's currently a pull request to add this to the Next documentation: https://github.com/vercel/next.js/pull/16443

Make sure to also respect the naming convention for client-side environment variables, prefixed with NEXT_PUBLIC_ if the environment variable will be used in client-facing code.

like image 23
Christopher Borchert Avatar answered Jan 01 '23 13:01

Christopher Borchert