nestjs 开玩笑在 10 分钟后 circleci 超时

nestjs jest times out after 10 minutes circleci

我有一个带有 jest e2e 测试套件的 nestjs 应用程序。 运行 本地大概需要13s~。然而,当尝试在 circleci 上 运行 它们时,测试挂起并且似乎没有成功退出。它们在 10 分钟后超时并失败。我不确定是什么导致了这种行为。

/.circleci/config.yml

version: 2.1
jobs:
  run_tests:
    docker:
      - image: circleci/node:10
    steps:
      - checkout #cloning git repo
      - run:
          name: Install npm dependencies
          command: |
            npm install --save
      - run:
          name: Run unit tests
          command: |
            NODE_ENV=test && node node_modules/.bin/jest
          environment:
            DATABASE_URL: postgres://_:_:@localhost:5432/testdb
      - run:
          name: Run e2e tests
          command: |
            NODE_ENV=test && node --inspect-brk node_modules/.bin/jest --runInBand --config ./test/jest-e2e.json --watchAll=false
          environment:
            DATABASE_URL: postgres://_:_:@localhost:5432/testdb
      - store_test_results:
          path: test-results
workflows:
  build_test:
    jobs:
      - run_tests

test/jest-e2e.json

{
  "moduleFileExtensions": ["js", "json", "ts"],
  "rootDir": ".",
  "testEnvironment": "node",
  "testRegex": ".e2e-spec.ts$",
  "transform": {
    "^.+\.(t|j)s$": "ts-jest"
  },
  "verbose": true
}

测试设置

beforeAll(async () => {
    const rootModule: TestingModule = await Test.createTestingModule({
      imports: [RootModule]
    }).compile();

    app = rootModule.createNestApplication();
    await app.init();
    shopboxService = app.select(ShopboxModule).get(ShopboxService);
    clothesService = app.select(ClothesModule).get(ClothesService);
    await shopboxService.deleteTags();
  });

  it('authenticates a user and includes a jwt token in the response', async () => {
    const response = await request(app.getHttpServer())
      .post('/auth/login')
      .send({ email: 'myemail@example.com', password: '123456789' })
      .expect(201);

    adminAccessToken = response.body.token;

    expect(adminAccessToken).toMatch(
      /^[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*$/
    );
  });

测试拆解

  afterAll(async () => {
    try {
      await shopboxService.deleteTags();
    } catch (e) {
      console.warn('error', e);
    } finally {
      await app.close();
    }
  });

删除 --inspect-brk circleci 后开始提供测试反馈。

FAIL  test/user-store-reservation-flow.e2e-spec.ts (37.493 s)
  User create store reservation flow
    ✕ authenticates a user and includes a jwt token in the response (2 ms)
    ✕ authenticates a user and includes a jwt token in the response
    ✕ creates a user
    ✕ creates a reservation, check that it exists in shopbox (4 ms)
    ✕ create clothing on storeReservation, check that it has the right properties
    ✕ check that clothing exists in shopbox, and has correct price, barcode, user, tag and reservation (1 ms)
    ✕ fails when persisting another one, should not persist to shopbox
    ✕ updating shopbox stock should retrieve stock 1
    ✕ get current reservations should return 1 (1 ms)
    ✕ should not be able to create a second reservation
    ✕ delete clothing should fail on user, but be accepted as employee
    ✕ delete clothing should fail on user, but be accepted as employee
    ✕ create a new piece of clothing and assert that it exists in the db and shopbox (1 ms)
    ✕ delete reservation and check that the clothing and reservation is terminated in postgres and does not exist in shopbox

  ● User create store reservation flow › authenticates a user and includes a jwt token in the response

    Timeout - Async callback was not invoked within the 30000 ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 30000 ms timeout specified by jest.setTimeout.

      at mapper (../node_modules/jest-jasmine2/build/queueRunner.js:27:45)

  ● User create store reservation flow › authenticates a user and includes a jwt token in the response

    TypeError: Cannot read property 'getHttpServer' of undefined

      38 | 
      39 |   it('authenticates a user and includes a jwt token in the response', async () => {
    > 40 |     const response = await request(app.getHttpServer())
         |                                        ^
      41 |       .post('/auth/login')
      42 |       .send({ email: '_', password: '123456789' })
      43 |       .expect(201);

      at Object.it (user-store-reservation-flow.e2e-spec.ts:40:40)

我不确定为什么会失败,因为它在本地按预期工作。

此外,在 运行测试之后,数据库连接似乎没有正确关闭

Time:        37.537 s
Ran all test suites.
[Nest] 624   - 11/21/2020, 12:37:07 AM   [ExceptionHandler] Unable to connect to the database. Retrying (1)...
Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
[Nest] 624   - 11/21/2020, 12:37:40 AM   [ExceptionHandler] Unable to connect to the database. Retrying (2)... +33005ms
[Nest] 624   - 11/21/2020, 12:38:13 AM   [ExceptionHandler] Unable to connect to the database. Retrying (3)... +33007ms
[Nest] 624   - 11/21/2020, 12:38:46 AM   [ExceptionHandler] Unable to connect to the database. Retrying (4)... +33004ms
[Nest] 624   - 11/21/2020, 12:39:19 AM   [ExceptionHandler] Unable to connect to the database. Retrying (5)... +33005ms
[Nest] 624   - 11/21/2020, 12:39:52 AM   [ExceptionHandler] Unable to connect to the database. Retrying (6)... +33006ms

有多个错误。一开始挂是因为--inspect-brk,因为它在程序开始时设置了调试断点

然后我的两个数据库 postgres 和 mongodb 遇到了多个错误。它们挂起或无法正确连接。

为了让它发挥作用,我必须

  • 在容器中设置一个Mongodb镜像
  • 在容器中设置 Postgres 镜像
  • 安装 postgres 扩展
  • 删除种子脚本中的封装事务。

.circleci/config.yml

version: 2.1
jobs:
  run_tests:
    docker:
      - image: circleci/node:10
      - image: circleci/postgres:9.6.8-alpine-postgis
        auth:
          username: ?
          password: ? # context / project UI env-var reference
        environment:
          POSTGRES_USER: ?
          POSTGRES_DB: ?
          POSTGRES_PASSWORD: ?
      - image: circleci/mongo:4.4.1
        environment:
          DATABASE_URL: mongodb://localhost/?
    steps:
      - checkout #alias for git clone\
      - run:
          name: Installing psql client
          command: |
            sudo apt install postgresql-client
      - run:
          name: Waiting for PostgreSQL to start
          command: |
            for i in `seq 1 10`;
            do
              nc -z localhost 5432 && echo Success && exit 0
              echo -n .
              sleep 2
            done
            echo Failed waiting for Postgres && exit 1
      - run:
          name: Installing postgres contributions
          command: |
            sudo apt-get -qq update
            sudo apt-get -qq install postgresql-contrib
      - run:
          name: Restarting postgres
          command: |
            sudo service postgresql restart
      - run:
          name: Install extensions for postgres
          command: |
            psql -U ? -d ? -h localhost -p 5432 -c "CREATE EXTENSION btree_gist;"
      - run:
          name: Waiting for MongoDB to be ready
          command: |
            for i in `seq 1 30`;
            do
              nc -z localhost 27017 && echo Success && exit 0
              echo -n .
              sleep 1
            done
            echo Failed waiting for MongoDB && exit 1
      - run:
          name: Install npm dependencies
          command: |
            npm install --save
      - run:
          name: Run unit tests
          command: |
            NODE_ENV=test && node node_modules/.bin/jest
      - run:
          name: Run e2e tests
          command: |
            NODE_ENV=test && node node_modules/.bin/jest --runInBand --config ./test/jest-e2e.json --watchAll=false --detectOpenHandles
      - store_test_results:
          path: test-results
      - store_artifacts:
          path: test-results

workflows:
  build_test:
    jobs:
      - run_tests

估计是效率低下,不得不这样安装psql客户端和依赖