Typescript with Jest - "ReferenceError: beforeAll is not defined"

Viewed 8664

So I have a project where I am using:

  • Typescript
  • TypeORM
  • Type-graphql
  • Jest

I had it working just fine until I started writing my tests. The test files are inside of each entity folder. For example:

  Student
  |- Student.ts
  |- Student.test.ts
  |- StudentService.ts

When I run Jest to execute my tests, everything is just fine and works as expected. However, if I run nodemon --exec ts-node src/index.ts I get an error for the first Jest related function I have, whether it is beforeAll(), afterAll(), describe()...

My tsconfig.json is:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "lib": ["dom", "es6", "es2017", "esnext.asynciterable"],
    "sourceMap": true,
    "outDir": "./dist",
    "moduleResolution": "node",

    "types": ["jest", "node"],

    "removeComments": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  },
  "include": ["**/*.ts"],
  "exclude": ["node_modules", "**/*.test.ts", "**/*.spec.ts"]
}

My jest.config.js is:

module.exports = {
  preset: "ts-jest",
  testEnvironment: "node",
  roots: ["./src"],
  testMatch: [
    "**/__tests__/**/*.+(ts|tsx|js)",
    "**/?(*.)+(spec|test).+(ts|tsx|js)",
  ],
  transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
  },
};

From what I can understand, typescript is trying to compile my test files even when they are set to be excluded inside of the tsconfig.

More information that might be useful: I have jest, ts-jest and @types/jest as devdependencies. I have only one tsconfig.json file and one jest.config.js

Any idea on how to fix this?

Update 1

I forgot to post the one of the test files, although I don't think it is related to the issue or is the cause of my problem...

import { createTestConnection } from "../../test/createTestConnection";
import { graphqlCall } from "../../test/graphqlCall";
import { Connection } from "typeorm";

let conn: Connection;

beforeAll(async () => {
  console.log("Test started");

  conn = await createTestConnection(true);
});

afterAll(() => {
  conn.close();
});

const addStudentWithoutGuardian = `
  mutation addStudentWithoutGuardian($studentInput: StudentInput!) {
  addStudent(studentInput: $studentInput) {
    id
  }
}
`;

describe("Student", () => {
  it("create only with basic information", async () => {
    console.log(
      await graphqlCall({
        source: addStudentWithoutGuardian,
        variableValues: {
          studentInput: {
            firstName: "Harry",
            lastName: "Smith",
            dateOfBirth: "1997-01-30",
            pronoun: 0,
            gender: 0,
            phone: "1231231234",
            email: "harry@gmail.com",
            addressLine1: "123 Avenue",
            city: "Toronto",
            state: "Ontario",
            postalCode: "X1X1X1",
            gradeLevel: "grade level",
          },
        },
      })
    );
  });
});

Update 2

Error stack

$ nodemon --exec ts-node src/index.ts
[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: ts,json      
[nodemon] starting `ts-node src/index.ts`   
(node:11716) UnhandledPromiseRejectionWarning: ReferenceError: beforeAll is not defined
    at Object.<anonymous> (G:\Documents\repos\tms\server\src\model\Student\Student.test.ts:7:1)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Module.m._compile (G:\Documents\repos\tms\server\node_modules\ts-node\src\index.ts:1056:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Object.require.extensions.<computed> [as .ts] (G:\Documents\repos\tms\server\node_modules\ts-node\src\index.ts:1059:12)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at G:\Documents\repos\tms\server\src\util\DirectoryExportedClassesLoader.ts:41:22
(Use `node --trace-warnings ...` to show where the warning was created)
(node:11716) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:11716) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
[nodemon] clean exit - waiting for changes before restart

Update 3

My index.ts

import "reflect-metadata";
import { createConnection } from "typeorm";
import express from "express";
import { ApolloServer } from "apollo-server-express";
import cors from "cors";
import { createSchema } from "./utils/createSchema";

(async () => {
  const app = express();

  app.use(
    cors({
      origin: ["http://localhost:3000"],
      credentials: true,
    })
  );

  await createConnection();

  const apolloServer = new ApolloServer({
    schema: await createSchema(),
    context: ({ req, res }) => ({ req, res }),
  });

  apolloServer.applyMiddleware({ app, cors: false });

  app.listen(4000, () => {
    console.log("Express server started");
  });
})();

Update 4

My dependenciesand devDependencies

"dependencies": {
    "apollo-server-express": "^2.19.2",
    "class-validator": "^0.13.1",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "faker": "^5.2.0",
    "graphql": "^15.4.0",
    "pg": "^8.5.1",
    "reflect-metadata": "^0.1.13",
    "type-graphql": "^1.1.1",
    "typeorm": "^0.2.30",
    "typeorm-seeding": "^1.6.1"
  },
  "devDependencies": {
    "@types/express": "^4.17.11",
    "@types/faker": "^5.1.6",
    "@types/jest": "^26.0.20",
    "@types/node": "^14.14.21",
    "jest": "^26.6.3",
    "nodemon": "^2.0.7",
    "ts-jest": "^26.5.0",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
  },
3 Answers

For anybody who was trying to get a globalSetup to work in Jest and getting ReferenceError: beforeAll is not defined - I'll save you a few hours of hitting your head against the desk:

  1. Define your setup file - jest.setup.ts
  2. Use the setupFilesAfterEnv property. i.e. setupFilesAfterEnv: ['./jest.setup.ts']

Jest globals are not available in setupFiles orglobalSetup

So I just figured it out... It was really silly...

The ormconfig.json has a path to scan all the entities, like this:

"entities": ["src/model/**/*.ts"],

I had to change to:

"entities": ["src/model/**/!(*.test.ts)"],

This was the reason why some of my test files were being loaded and then throwing errors related to Jest functions not being found.

I found this solution after searching for a way to exclude certain files in a similar way tsconfig.json does, however, TypeORM has no exclude parameter so it has to be done with like above.

Github issue with the suggestion

Thanks for all the help.

check that package.json has all dependencies:

{
  "name": "ts_test",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "jest": "^26.6.3",
    "ts-jest": "^26.5.0",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
  }
}

I ran with you configs: yarn jest It works.

 PASS  src/sum.test.ts
  ✓ adds 1 + 2 to equal 3 (4 ms)

  console.log
    Test started

      at src/sum.test.ts:4:11

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.023 s
Ran all test suites.
Done in 5.06s.

sum.test.ts

import sum from './sum';

beforeAll(async () => {
  console.log("Test started");
});

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

sum.ts

function sum(x:number, y:number):number {
  return x + y;
}

export default sum

run with nodemon

yarn nodemon --exec ts-node src/sum.ts
yarn run v1.22.4
$ /home/.../ts_test/node_modules/.bin/nodemon --exec ts-node src/sum.ts
[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: ts,json
[nodemon] starting `ts-node src/sum.ts`
[nodemon] clean exit - waiting for changes before restart
Related