Глобальная настройка Jest приводит к непоследовательному прохождению/непрохождению теста

Я пытаюсь протестировать API с помощью шутки. Изначально все мои тесты были в одном файле и все тесты проходили. Я хотел разделить свои тесты на разные файлы. Для этого я пытаюсь использовать глобальный установочный файл с beforeEach и afterEach. Проблема в том, что иногда я запускаю тесты, и они проходят, а иногда они терпят неудачу (каждый раз разные тесты проходят и разные проваливаются).

пакет.json

{
"jest": {
    "verbose": true,
    "bail": false,
    "preset": "@shelf/jest-mongodb",
    "setupFilesAfterEnv": [
      "<rootDir>/jest.setup.js"
    ],
    "globals": {
      "authHeaders": {},
      "authId": null
    }
  },
}

jest.setup.js

const app = require("./index")
const supertest = require("supertest")
const request = supertest(app)
const db = require("./src/db")
const jwtDecode = require("jwt-decode")
const getAuthToken = require("./src/utils/getAuthToken")

let token
let decodedJwt

const getAuthHeaders = token => ({
  Authorization: `Bearer ${token}`
})

beforeEach(async done => {
  //setup globals available in all tests

  token = await getAuthToken()
  token = JSON.parse(token)["access_token"]
  decodedJwt = jwtDecode(token)
  authId = decodedJwt.sub
  authHeaders = getAuthHeaders(token)

  // Ensure that we have a users collection with our test user
  // who can then call the api
  await request
    .post("/v1/users")
    .set(authHeaders)
    .send({ email: "[email protected]" })
    .expect(200)

  done()
})

afterEach(async done => {
  // Delete the users collection
  await db.instance.dropUsers()
  await db.instance.dropAgencies()

  done()
})

пользователи.test.js

const app = require("../../../../index")
const supertest = require("supertest")
const request = supertest(app)
const faker = require("faker")

describe("/v1/users/:id", () => {
  test("should return an error when the users do not have a mutual agency", async done => {
      if (!authHeaders || !authId) {
        expect(true).toBe(false)
      }
      let testUserId = null
      let email = faker.internet.email()

      await request
        .post("/v1/users")
        .set(authHeaders)
        .send({ email })
        .expect(200)
        .then(({ body }) => (testUserId = body._id))

      await request
        .get("/v1/users/" + testUserId)
        .set(authHeaders)
        .expect(200)
        .then(({ body }) => {
          expect(body).toHaveProperty("error")
          expect(body.error).toHaveProperty("message")
        })

      done()
    })
})

Я могу запустить вышеуказанное один раз, и через несколько мгновений оно пройдет и снова запустится, и оно потерпит неудачу.


Редактировать:

После дальнейшего расследования кажется, что проблема связана с тем, что функция afterEach не удаляет коллекцию Users. Когда я записываю в консоль ответ на запрос, сделанный в beforeEach в файле jest.setup.js, я получаю ответ об ошибке, в котором говорится, что пользователь для данного электронного письма уже существует.


person mrmadhat    schedule 26.01.2020    source источник
comment
Когда вы определяете тест как async, вам не нужно вызывать метод done. Когда вы видите, что тест не проходит, что это за ошибка?   -  person mgarcia    schedule 26.01.2020
comment
Я обновил свой вопрос, чтобы предоставить больше информации о том, что я вижу   -  person mrmadhat    schedule 26.01.2020
comment
Мммм, есть ли какой-нибудь другой тест, который заполняет базу данных? Возможно, у вас есть тест, который вставляет запись в базу данных после выполнения хука afterEach.   -  person mgarcia    schedule 28.01.2020
comment
Есть другой тест, который заполняет базу данных, но дело в том, что я помещаю оператор debbuger в beforeEach и один в afterEach и прохожу тесты в более медленном темпе, все тесты проходят. Мне интересно, если это какая-то проблема с задержкой от БД, но если я жду этого, то это невозможно. Так что я в тупике   -  person mrmadhat    schedule 29.01.2020


Ответы (1)


Проблема была вызвана одновременным выполнением нескольких тестов. Добавление флага --runInBand (который заставляет тест выполняться последовательно) устраняет проблему.

Ошибка в моем мышлении заключалась в том, что я предположил, что безопасно добавить запись пользователя в базу данных beforeEach и удалить ее afterEach, не принимая во внимание, что если два теста выполняются одновременно, один из них всегда будет терпеть неудачу, поскольку пользователь уже существует в базе данных.

В свете этого я думаю, что было бы неплохо реорганизовать мой установочный файл, чтобы мой тестовый пользователь создавался только один раз для всех тестов, но мне нужно учитывать последствия этого.

РЕДАКТИРОВАТЬ:

Я обнаружил, что могу успешно запустить тест без флага runInBand, переключив свою облачную базу данных atlas на mongodb-memory-server во время тестов.

person mrmadhat    schedule 29.01.2020