Функция, определенная в блоке «До», не завершается до запуска тестов в Mocha - PullRequest
0 голосов
/ 24 октября 2019

Я создаю несколько тестов, используя Mocha / Chai в моем проекте Node. В одном конкретном тесте мне нужно сначала сохранить document в базе данных, а затем извлечь его и выполнить некоторые проверки найденного документа.

Проблема, с которой я сталкиваюсь, заключается в том, что проверки itвыполняются до завершения сохранения документа в базе данных. Я не понимаю, почему это происходит, потому что я делаю сохранение в блоке before(), который, согласно документации Mocha, должен выполняться до тестов в этом же блоке описания, см. Ниже из документации:

> With its default "BDD"-style interface, Mocha provides the hooks
> before(), after(), beforeEach(), and afterEach(). These should be used
> to set up preconditions and clean up after your tests.
> 
> describe('hooks', function() {   before(function() {
>     // runs before all tests in this block   });
> 
>   after(function() {
>     // runs after all tests in this block   });
> 
>   beforeEach(function() {
>     // runs before each test in this block   });
> 
>   afterEach(function() {
>     // runs after each test in this block   });
> 
>   // test cases });

Чтобы уточнить, когда я запускаю тест во второй раз (и все последующие разы), все проверки проходят, потому что к тому времени он может найти документ в БД.

Что мне здесь не хватает?

Вот мой код:

const assert = require("chai").assert;
const expect = require("chai").expect;
const chai = require("chai");
chai.use(require("chai-datetime"));
const Agenda = require('agenda');

const config = require('./../../configuration');
const url = config.get('MONGO_URL');
const dbName = config.get('MONGO_DATABASE');
const collection = config.get('MONGO_COLLECTION');
const createAgendaJob = require('./../../lib/agenda-jobs/contact-firstname-to-proper-case');

const MongoClient = require('mongodb').MongoClient;
const client = new MongoClient(url);

describe("Contact FirstName to Proper Case", async function () {
  const jobName = "Contact FirstName To Proper Case";
  const testDate = new Date(2019, 01, 01);
  let result;
  let agenda;
  this.timeout(2000);
  before(async function () {
    const connectionOpts = {
      db: {
        address: `${url}/${dbName}`,
        collection
      }
    };

    agenda = new Agenda(connectionOpts);
    await new Promise(resolve => agenda.once('ready', resolve));
    await createAgendaJob(agenda); // Here is where I save the job to the DB
  });
  client.connect(async function (err) {
    assert.equal(null, err);

    const db = await client.db(dbName);

    result = await db.collection("jobs").findOne({
      "name": jobName
    });

    client.close();
  });
  it("should have a property 'name'", function () {
    expect(result).to.have.property("name");
  });
  it("should have a 'name' of 'Contact FirstName To Proper Case'", function () {
    expect(result.name).to.equal("Contact FirstName To Proper Case");
  });
  it("should have a property 'type'", function () {
    expect(result).to.have.property("type");
  });
  it("should have a 'type' of 'normal'", function () {
    expect(result.type).to.equal("normal");
  });
  it("should have a property 'repeatTimezone'", function () {
    expect(result).to.have.property("repeatTimezone");
  });
  it("should have a property 'repeatInterval'", function () {
    expect(result).to.have.property("repeatInterval");
  });
  it("should have a property 'lastModifiedBy'", function () {
    expect(result).to.have.property("lastModifiedBy");
  });
  it("should have a property 'nextRunAt'", function () {
    expect(result).to.have.property("nextRunAt");
  });
  it("should return a date for the 'nextRunAt' property", function () {
    assert.typeOf(result.nextRunAt, "date");
  });
  it("should 'nextRunAt' to be a date after test date", function () {
    expect(result.nextRunAt).to.afterDate(testDate);
  });
});

Я также пытался поместить проверки it в последующий блок describe(), ноэто также не сработало (тот же результат - документ найден только во ВТОРОМ запуске тестового файла):

const assert = require("chai").assert;
const expect = require("chai").expect;
const chai = require("chai");
chai.use(require("chai-datetime"));
const Agenda = require('agenda');

const config = require('./../../configuration');
const url = config.get('MONGO_URL');
const dbName = config.get('MONGO_DATABASE');
const collection = config.get('MONGO_COLLECTION');
const createAgendaJob = require('./../../lib/agenda-jobs/contact-firstname-to-proper-case');

const MongoClient = require('mongodb').MongoClient;
const client = new MongoClient(url);

describe("Contact FirstName to Proper Case", async function () {
  const jobName = "Contact FirstName To Proper Case";
  const testDate = new Date(2019, 01, 01);
  let result;
  let agenda;
  this.timeout(2000);
  before(async function () {
    const connectionOpts = {
      db: {
        address: `${url}/${dbName}`,
        collection
      }
    };

    agenda = new Agenda(connectionOpts);
    await new Promise(resolve => agenda.once('ready', resolve));
    await createAgendaJob(agenda); // Here is where I save the job to the DB
  });
  client.connect(async function (err) {
    assert.equal(null, err);

    const db = await client.db(dbName);

    result = await db.collection("jobs").findOne({
      "name": jobName
    });

    client.close();
  });
  describe("Check Contact FirstName To ProperCase Found Job", function () {
    it("should have a property 'name'", function () {
      expect(result).to.have.property("name");
    });
    it("should have a 'name' of 'Contact FirstName To Proper Case'", function () {
      expect(result.name).to.equal("Contact FirstName To Proper Case");
    });
    it("should have a property 'type'", function () {
      expect(result).to.have.property("type");
    });
    it("should have a 'type' of 'normal'", function () {
      expect(result.type).to.equal("normal");
    });
    it("should have a property 'repeatTimezone'", function () {
      expect(result).to.have.property("repeatTimezone");
    });
    it("should have a property 'repeatInterval'", function () {
      expect(result).to.have.property("repeatInterval");
    });
    it("should have a property 'lastModifiedBy'", function () {
      expect(result).to.have.property("lastModifiedBy");
    });
    it("should have a property 'nextRunAt'", function () {
      expect(result).to.have.property("nextRunAt");
    });
    it("should return a date for the 'nextRunAt' property", function () {
      assert.typeOf(result.nextRunAt, "date");
    });
    it("should 'nextRunAt' to be a date after test date", function () {
      expect(result.nextRunAt).to.afterDate(testDate);
    });
  });
});

1 Ответ

1 голос
/ 24 октября 2019

Он не it запущен до того, как before закончен, но он запускается раньше всего:

    client.connect(async function (err) {
     ...
    });

Мокко, когда создается тестовый набор, запускающий код, подобный этому:

  • вызовите каждую функцию, переданную describe

    • , соберите все it s и before/after* хуков
    • , когда на самом деле вызывается ваш client.connect фрагмент!
  • затем, после создания всего набора / тестового дерева, для каждого набора

    • вызовы, подходящие перед * hooks
    • вызвать все it s - тесты, возможно окруженные before/afterAll крючками
    • вызов after крючками

Каждый крюк / тестовый прогон ожидает завершенияпо крайней мере, в вашем случае, поскольку вы правильно используете async / await

Также обратите внимание, что это очень подозрительно:

await setTimeout(() => {
  console.log('finished pausing for 5 seconds...');
}, 5000);

Это ничего не ждет, потому что setTimeout возвращаеттаймер (число возможно), и не совсем ясно, что await должен делать с этими данными, так как это не обещает. Конечно, он не ждет 5 секунд.

Правильное обещанное ожидание выглядит следующим образом:

await new Promise(resolve => setTimeout(resolve, 5000))
...