express.Router() returns Undefined when testing with Jest/Supertest

30 Views Asked by At

I have a Node.js/Express.js API and I want to test the routes using Jest and Supertest. The app itself works without issues but when I run the test, I keep getting the same error:

  ● Test suite failed to run

TypeError: Cannot read properties of undefined (reading 'Router')

  3 | import { requestAuth2 } from "../middleware/requestAuth2.js";
  4 | import { ListUsersCommandOutput } from "@aws-sdk/client-cognito-identity-provider";
> 5 | const router = express.Router();
    |                        ^
  6 |
  7 | router.get("/", requestAuth2, async function (req, res, next) {
  8 |   next();

  at Object.<anonymous> (routes/users.ts:5:24)
  at Object.<anonymous> (app.ts:5:1)
  at Object.<anonymous> (__tests__/routes/auth.test.ts:2:1)

Do I have to mock also Express and the express Router?

Code for the express app is in a file named app.ts:

import express, { Request, Response, Express } from "express";
import cookieParser from "cookie-parser";
import cors from "cors";
import logger from "morgan";
import usersRouter from "./routes/users.js";
import authRouter from "./routes/auth.js";
import monitoringRouter from "./routes/monitoring.js";
import bucketRouter from "./routes/buckets.js";
import dynamoDBRouter from "./routes/dynamoDB.js";
import stepFunctionsRouter from "./routes/stepFunctions.js";
import queueRouter from "./routes/queue.js";

const app: Express = express();

app.use(function (_req, res, next) {
  res.header("Access-Control-Allow-Origin", "true");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept",
  );
  res.header("Access-Control-Expose-Headers", "Set-Cookie, Cookie");
  next();
});

app.use(logger("dev"));
app.use(
  cors({
    origin: true,
    credentials: true,
  }),
);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

app.use(`${process.env.ROUTE}/auth`, authRouter);
app.use(`${process.env.ROUTE}/monitoring`, monitoringRouter);
app.use(`${process.env.ROUTE}/users`, usersRouter);
app.use(`${process.env.ROUTE}/bucket`, bucketRouter);
app.use(`${process.env.ROUTE}/dynamodb`, dynamoDBRouter);
app.use(`${process.env.ROUTE}/stepfunctions`, stepFunctionsRouter);
app.use(`${process.env.ROUTE}/queue`, queueRouter);

app.get("/", (_: Request, res: Response) => {
  res.redirect("/api/monitoring/status");
});

app.use(function (_: Request, res: Response) {
  res
    .status(404)
    .json({ message: "We couldn't find what you were looking for " });
});

app.use(function (err: Error, _req: Request, res: Response) {
  console.error(err.stack);
  res.status(500).json(err);
});

export default app;

The auth route I'm trying to test looks like this:

import express, { Request, Response } from "express";
import {
  createUser,
} from "../controllers/AuthController.js";
const router = express.Router();

// REGISTER
router.post("/register", async (req: Request, res: Response) => {
  console.log("Req body", req.body);
  // Retrieve user data
  const email: string = req.body.email;
  const password: string = req.body.password;

  // Create new user in Cognito pool
  try {
    console.log("Attempting user creation.");
    const newUser = await createUser({
      email: email,
      password: password,
    });
    console.log("New user", newUser);
    res.status(201).json(newUser);
  } catch (error) {
    console.log("Error", error.message);
    res.status(400).send(error);
  }
});

This is my test:

import request from 'supertest';
import app from "../../app";
import {createUser} from "../../controllers/AuthController";

jest.mock("../../middleware/requestAuth2", () => ({
  requestAuth2: jest.fn(),
}));

jest.mock("../../controllers/AuthController", () => ({
  createUser: jest.fn(),
}));

describe('POST /api/auth/register', () => {
  it("should create a user", async () => {
   const mockCreateUser = createUser as jest.Mock;

    try {
      mockCreateUser.mockResolvedValueOnce("user created");
      await request(app)
        .post("/api/auth/register")
        .send({ email: "xxx", password: "xxx" })
        .expect("Content-Type", /json/)
        .expect(201);

    } catch (error) {
      console.log(error);
    }
  });
});
0

There are 0 best solutions below