How to initialize manually next.js app (for testing purpose)?

Viewed 2855

I try to test my web services, hosted in my Next.js app and I have an error with not found Next.js configuration.

My web service are regular one, stored in the pages/api directory. My API test fetches a constant ATTACKS_ENDPOINT thanks to this file:

/pages/api/tests/api.spec.js

import { ATTACKS_ENDPOINT } from "../config"

...

describe("endpoints", () => {
   beforeAll(buildOptionsFetch)

   it("should return all attacks for attacks endpoint", async () => {
      const response = await fetch(API_URL + ATTACKS_ENDPOINT, headers)

config.js

import getConfig from "next/config"

const { publicRuntimeConfig } = getConfig()

export const API_URL = publicRuntimeConfig.API_URL

My next.config.js is present and is used properly by the app when started.

When the test is run, this error is thrown

    TypeError: Cannot destructure property `publicRuntimeConfig` of 'undefined' or 'null'.

  1 | import getConfig from "next/config"
  2 | 
> 3 | const { publicRuntimeConfig } = getConfig()

I looked for solutions and I found this issue which talks about _manually initialise__ next app.

How to do that, given that I don't test React component but API web service ?

3 Answers

I solved this problem by creating a jest.setup.js file and adding this line of code

First add jest.setup.js to jest.config.js file

// jest.config.js

module.exports = {
  // Your config
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};

AND then

// jest.setup.js

jest.mock('next/config', () => () => ({
  publicRuntimeConfig: {
    YOUR_PUBLIC_VARIABLE: 'value-of-env'  // Change this line and copy your env
  }
}))

OR

// jest.setup.js
import { setConfig } from 'next/config'
import config from './next.config'

// Make sure you can use "publicRuntimeConfig" within tests.
setConfig(config)

The problem I faced with testing with Jest was that next was not being initialized as expected. My solution was to mock the next module... You can try this:

/** @jest-environment node */
jest.mock('next');

import next from 'next';

next.mockReturnValue({
    prepare: () => Promise.resolve(),
    getRequestHandler: () => (req, res) => res.status(200),
    getConfig: () => ({
        publicRuntimeConfig: {} /* This is where you import the mock values */
    })
});

Read about manual mocks here: https://jestjs.io/docs/en/manual-mocks

In my case, I had to:

  1. Create a jest.setup.js file and
setConfig({
    ...config,
    publicRuntimeConfig: {
        BASE_PATH: '/',
        SOME_KEY: 'your_value',
    },
    serverRuntimeConfig: {
        YOUR_KEY: 'your_value',
    },
});
  1. Then add this in your jest.config.js file:
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
Related