Typeorm Connection “default” was not found when connection is created in jest globalSetup

早过忘川 提交于 2020-07-10 05:16:48

问题


I'm having a similar problem as in #5164 and this question. Consider the following working test code:

// 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: "Bob.Marley@contoso.com"
        }) {
          accountIdentifier
          name
          userName
        }
      }`
    )
    expect(actual.data).toMatchObject({
      data: {
        addAccount: {
          accountIdentifier: '7csdcd8-8a5f-49c3-ab9a-0198d42dd253',
          name: 'Jake, Bob (Braine-l’Alleud) JAM',
          userName: 'Bob.Marley@contoso.com',
        },
      },
    })

    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: "Bob.Marley@contoso.com"
        }) {
          accountIdentifier
          name
          userName
        }
      }`
    )
    expect(actual.data).toMatchObject({
      data: {
        addAccount: {
          accountIdentifier: '7csdcd8-8a5f-49c3-ab9a-0198d42dd253',
          name: 'Jake, Bob (Braine-l’Alleud) JAM',
          userName: 'Bob.Marley@contoso.com',
        },
      },
    })
  })
})

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

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

Keeping the require line in throws:

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

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 too. Found a similar issue here with a PR.

It seems like the tests are running in a fully isolated environment where they can't access the connection set up within globalSetup.

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()
})

回答1:


require('ts-node/register') shouldn't present in .ts files. They are already processed by TypeScript compiler.

This is not what globalSetup and globalTeardown are for. They run in Jest parent process and are evaluated once, while each test suite runs in child processes.

This can be achieved by providing a common setup in setupFilesAfterEnv option:

// jest.setup.ts
...
beforeAll(async () => {
  await createConnections()
})

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

Since Jest tests run in parallel, this will result in multiple database connections. If this is not desirable because of connection limit, Jest runInBand option needs to be used.

A setup for all tests not desirable because not all test suites need database connection, while they will unconditionally take time and occupy database connection pool. In this case jest.setup.ts can be imported directly in tests that use a database instead of setupFilesAfterEnv, no need to specify beforeAll and afterAll in each suite.



来源:https://stackoverflow.com/questions/62470047/typeorm-connection-default-was-not-found-when-connection-is-created-in-jest-gl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!