Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using globalSetup and globalTeardown with TypeScript #10178

Closed
DarkLite1 opened this issue Jun 19, 2020 · 8 comments
Closed

Using globalSetup and globalTeardown with TypeScript #10178

DarkLite1 opened this issue Jun 19, 2020 · 8 comments
Labels

Comments

@DarkLite1
Copy link

DarkLite1 commented Jun 19, 2020

Description

I'm having a similar problem as in #5164. Consider the following working test code with typeorm:

// AccountResolver.test.ts
describe('Account entity', () => {
  it('add account', async () => {
    await createConnections()
    const defaultConnection = getConnection('default')

    const actual = await callGraphql(
      `mutation {
        addAccount(options: {
          accountIdentifier: "7csdcd8-8a5f-49c3-ab9a-0198d42dd253"
          name: "Jake, Bob (Braine-l’Alleud) JAM"
          userName: "[email protected]"
        }) {
          accountIdentifier
          name
          userName
        }
      }`
    )
    expect(actual.data).toMatchObject({
      data: {
        addAccount: {
          accountIdentifier: '7csdcd8-8a5f-49c3-ab9a-0198d42dd253',
          name: 'Jake, Bob (Braine-l’Alleud) JAM',
          userName: '[email protected]',
        },
      },
    })

    await defaultConnection.query(`DELETE FROM Account`)
    await defaultConnection.close()
  })
})

The code to create a connection and close it should be executed before all tests and after all tests are done, that's why we've added it to globalSetup.ts and globalTeardown.ts:

// globalSetup.ts
require('ts-node/register')
import { createConnections } from 'typeorm'

module.exports = async () => {
  // console.log('jest setup')
  await createConnections()
}
// globalTeardown.ts
require('ts-node/register')
import { getConnection } from 'typeorm'

module.exports = async () => {
  const defaultConnection = getConnection('default')
  await defaultConnection.close()
}
// AccountResolver.test.ts
describe('Account entity', () => {
  it('add account', async () => {
    const defaultConnection = getConnection('default')
    await defaultConnection.query(`DELETE FROM Account`)
    
    const actual = await callGraphql(
      `mutation {
        addAccount(options: {
          accountIdentifier: "7csdcd8-8a5f-49c3-ab9a-0198d42dd253"
          name: "Jake, Bob (Braine-l’Alleud) JAM"
          userName: "[email protected]"
        }) {
          accountIdentifier
          name
          userName
        }
      }`
    )
    expect(actual.data).toMatchObject({
      data: {
        addAccount: {
          accountIdentifier: '7csdcd8-8a5f-49c3-ab9a-0198d42dd253',
          name: 'Jake, Bob (Braine-l’Alleud) JAM',
          userName: '[email protected]',
        },
      },
    })
  })
})

Omitting the line require('ts-node/register') from both files throws this error:

T:\Test\Brecht\Node\prod\backend\src\it-portal\entity\Account.ts:1
import {
^^^^^^
SyntaxError: Cannot use import statement outside a module

Keeping them in throws:

FAIL src/resolvers/AccountResolver.test.ts
Account entity
× add account (31 ms)
● Account entity › add account
ConnectionNotFoundError: Connection "default" was not found.

Version

    "jest": "^26.0.1",
    "ts-jest": "^26.1.0",
    "ts-node-dev": "^1.0.0-pre.44",
    "typescript": "^3.9.5"

Config

// jest.config.js
module.exports = {
  preset: 'ts-jest',
  globalSetup: './src/test-utils/config/globalSetup.ts',
  globalTeardown: './src/test-utils/config/globalTeardown.ts',
  setupFiles: ['./src/test-utils/config/setupFiles.ts'],
  moduleDirectories: ['node_modules', 'src'],
  globals: {
    'ts-jest': {
      tsConfig: 'tsconfig.json',
      diagnostics: {
        warnOnly: true,
      },
    },
  },
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80,
    },
  },
  coverageReporters: ['json', 'lcov', 'text', 'clover'],
}

Thank you for pointing out my mistakes. As I'm new I tried googling but couldn't really find an answer if this is me not understanding the tool or a bug in the tool.

Found a similar issue here with a PR and a similar question on StackOverflow..

Workaround

The only workaround I have found thus far is to add the following code to every test file:

beforeAll(async () => {
  await createConnections()
})

afterAll(async () => {
  const defaultConnection = getConnection('default')
  await defaultConnection.close()
})
@ecklf
Copy link

ecklf commented Jun 29, 2020

I have the same problem, but I think this sandboxing behavior is intended.

The only cleaner solution I found to this is using setupFilesAfterEnvto not copy/paste the logic into every test. If not all tests rely on the connection I consider migrating to testEnvironment.

@DarkLite1
Copy link
Author

You're right, I also define the database connection within the setupFilesAfterEnv now.

@impulse Could you elaborate what you mean with this statement:

If not all tests rely on the connection I consider migrating to testEnvironment.

@ecklf
Copy link

ecklf commented Jun 29, 2020

@impulse Could you elaborate what you mean with this statement:

From the docs setupFilesAfterEnv

A list of paths to modules that run some code to configure or set up the testing framework before each test file in the suite is executed

So this also affects tests that don't require a TypeORM connection.

With testEnvironment we could just add a comment to be more flexible on whether or not we connect to TypeORM for a specific test:

/**
 * @jest-environment ./path/to/typeorm-environment.ts
 */

@DarkLite1
Copy link
Author

DarkLite1 commented Jun 29, 2020

Thank you for the clarification, that looks pretty neat! This would also be useful to remove the argument --runInBand so tests could run in parallel using the same database connection per file. I don't know if they would use the same connection over different test files. Having a deeper look at that.

@ecklf
Copy link

ecklf commented Jun 29, 2020

This would also be useful to remove the argument --runInBand so tests could run in parallel using the same database connection per file

I think this sadly won't be possible

Note: TestEnvironment is sandboxed. Each test suite will trigger setup/teardown in their own TestEnvironment.

mithi added a commit to mithi/kingdom-rush-graphql that referenced this issue Oct 31, 2020
It is better to have two separate test environments (two test databases),
one for testing resolvers (which is closer to an integration test), and the other for testing everything else.

When testing graphql resolvers, seeding the database should only be done once as this is a slow operation. 
Currently, using 'globalSetup` and `globalTeardown` with jest doesn't work for setting up the `typeorm` database.
The tests are not able to find the connection. 
See:
#73
typeorm/typeorm#5308
jestjs/jest#10178

It is also not efficient to remove all of the entries for this database in order to start with a clean slate for
testing the models and testing the seeding operations. So what we do here is we have two test databases. 
1. a prepopulated frozen test database (called `test_db`) to be used by the graphql resolvers
2. an empty database (called `empty_test_db`) which we can safely mutate (like inserting and deleting operation) to test seeding functions, among others

So this pull request updates all the scripts and other files for the current tests to work

I have also refactored some of the test scripts to be more readable and also added 
a simple test for testing the `abilityById` graphql query..
@github-actions
Copy link

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 14 days.

@github-actions github-actions bot added the Stale label Feb 25, 2022
@github-actions
Copy link

This issue was closed because it has been stalled for 7 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.

@github-actions
Copy link

github-actions bot commented May 5, 2022

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants