Обеспечение получения документа без использования setTimeout () в тесте Mocha - PullRequest
0 голосов
/ 25 октября 2019

Я написал несколько тестов в своем проекте Node, используя Mocha и Chai. В одном из моих тестов я создаю задание повестки дня.js, а затем сохраняю его в базе данных. Затем я извлекаю этот документ из базы данных MongoDB и проверяю его. После многочисленных конфигураций я нашел конструкцию для теста, которая работает. Но чтобы это работало, мне пришлось добавить setTimeout() в первый блок it, потому что в противном случае проверки it запускаются до того, как документ извлекается из базы данных.

Хотя следующие строительные работы, я хотел бы знать, что было бы лучшим способом сделать это. Мне кажется, что весь смысл блока before в Mocha состоит в том, чтобы гарантировать, что любая работа, определенная в нем, выполняется ДО выполнения проверок it. Похоже, этого не происходит в моем случае - отсюда и необходимость setTimeout(). Итак, как я могу сделать это, не прибегая к использованию `setTimeout ()?:

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(10000);
  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);
  });
  describe("Check Contact FirstName To ProperCase Found Job", async function () {
    let result;
    before(async function () {
      await 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'", async function () {
      await new Promise(resolve => setTimeout(resolve, 1000)); // Here is the setTimout()
      expect(result).to.have.property("name");
    });
    it("should have a 'name' of 'Contact FirstName To Proper Case'", async 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 голос
/ 25 октября 2019

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

//...
before(function () {
  return new Promise((resolve, reject) => {
    client.connect(async function (err) {
      if(err) return reject(err);
      try {
        const db = await client.db(dbName);

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

        client.close();
      } catch(err){
        return reject(err);
      }
      return resolve();
    });
  });
})
//...

В качестве альтернативы можно вызвать обратный вызов done, передав истинное значение в случае ошибки.

//...
before(function (done) {
  client.connect(async function (err) {
    if(err) return done(err);
    try {
      const db = await client.db(dbName);

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

      client.close();
    } catch(err){
      return done(err);
    }
    done();
  });
})
//...
...