next.js: Unable to test middleware with Jest

What version of Next.js are you using?

12.0.7

What version of Node.js are you using?

16.13.1

What browser are you using?

Firefox

What operating system are you using?

Pop!_OS

How are you deploying your application?

Vercel

Describe the Bug

When trying to test _middleware.js with Jest, I’m unable to import { NextResponse } from 'next/server' without throwing an error SyntaxError: Unexpected token 'export' because next/server uses export { NextRequest } in line 1.

Expected Behavior

I would like to be able to test my _middleware.js authentication methodology.

To Reproduce

  1. Create a Next app with the aforementioned versions.
  2. Create a _middleware.js
  3. Create a test for it in Jest.
  4. Try to import NextResponse from next/server.
  5. Run tests.
  6. Get error.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 3
  • Comments: 18 (5 by maintainers)

Commits related to this issue

Most upvoted comments

We aim to ship very soon a Jest runtime that will allow you to test middleware code without doing anything special. Just a heads up that we are working on this!

My solution was create src/__mocks__/next/server.js with the following content, that fixed the issue to me

import { NextRequest } from 'next/dist/server/web/spec-extension/request';
import { NextResponse } from 'next/dist/server/web/spec-extension/response';

export { NextRequest, NextResponse };

@gom3s yeah node doesn’t include fetch and you have to use a polyfill.

Import node-fetch or isomorphic-fetch in your jest.setup.ts

It works!! thank you @wovalle

final setup that works for me

// jest.setup.ts
import 'isomorphic-fetch'
// jest.config.js
const ignoredModules = ['next'].join('|')

module.exports = {
  verbose: true,
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
  testPathIgnorePatterns: ['/node_modules/', '/.next/'],
  testEnvironment: 'jest-environment-jsdom',
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'ts-jest'
  },
  transformIgnorePatterns: [`/node_modules/(?!${ignoredModules})`]
}

Yeah I guessed so, but what’s weird is that transformIgnorePatterns is not being respected by next/jest. I had to go back to use @swc/jest directly since I wanted to test middleware functions.

In case someone else is interested:

// jest.config.js

const ignoredModules = ["next"].join("|")

module.exports = {
  clearMocks: true,
  transformIgnorePatterns: [`/node_modules/(?!${ignoredModules})`],
  testEnvironment: "jest-environment-jsdom",
  transform: {
    "^.+\\.(t|j)sx?$": ["@swc/jest"],
  },
  setupFiles: ["<rootDir>/jest.setup.js"],
}

The real deal is adding node_modules/next to transformIgnorePatterns. Probably it could be optimized by only transforming files under next/server but this is good enough for my use case