在 Mocha 中执行测试之前如何强制 before() 完成?

How to enforce before() to complete before executing tests in Mocha?

我是 JavaScript 生态系统的新手。我正在尝试使用 Mocha/Chai 为我的 REST API 编写几个 API 测试。我的要求是我必须在 运行 每个测试用例之前清理我的数据库。因此,我在名为 dbCleanup.js

的文件中编写了以下代码
var config = require("config.json");
const pg = require('pg');

var connectionString = config.pgConnectionString
console.log("DB Connection String: ", connectionString)

function dbCleanup() {

    var dbTables = ["projects", "employees"];

    var pgClient = new pg.Client(connectionString);

    var promise = new Promise(function (resolve, reject) {
        pg.connect(connectionString, (err, pgClient, done) => {
            if (err) {
                done();
                console.log(err);
                reject();
            }

            for (i = 0; i < dbTables.length; i++) {
                query = "TRUNCATE " + dbTables[i] + " CASCADE;"
                pgClient.query(query, function (err, res) {
                    if (err) {
                        done();
                        console.error('error running query', err);
                        reject();
                    }
                    resolve();
                });
            }
        });
    });

    pgClient.end()

    return promise;
}

exports.dbCleanup = dbCleanup;

我有另一个名为 globalBefore.js 的文件,其中包含以下代码:

var dbCleanup = require('./dbCleanup.js').dbCleanup;

function _beforeClean(done) {
    try {
        dbCleanup()
            .then(done)
    } catch (err) {
        console.error(err);
    }
}

exports.beforeCleanup = _beforeClean;

现在在我的 Mocha test.js 文件中,我尝试按如下方式调用数据库清理函数:

var request = require("request");
var rp = require("request-promise");
var config = require("../config.json");
var expect = require('chai').expect;
var data = require("./data.json");

var globalBefore = require("../globalBefore.js");


describe("POST /employees/", function () {

    console.log("clearing db tables...")
    before(globalBefore.beforeCleanup, function (done) {
        done();
    });

    beforeEach(function (done) {
    ... do some business logic related work here ...
    });


    it.only('Try create an employee', function (done) {
    ... API call to create an employee and use Chai assertions to validate ...
    });
});

我面临的问题是,Mocha 甚至在 dbCleanup() 函数完成之前就继续 运行 我的测试。这导致我的数据库失效并且我遇到了不希望的行为。

SO 社区的任何人都可以帮忙吗?我尝试了可以​​在网上找到的各种选项,但无法解决问题。如代码片段所示,我希望使用Promise应该已经解决了问题

为了更通用,我如何强制执行 before 子句中的指令,以便在 Mocha 运行测试?

谢谢!

您使用 before 的方式有误。试试这个:

before(function (done) {
    globalBefore.beforeCleanup(done);
});

before(globalBefore.beforeCleanup);

globalBefore.js中:

var dbCleanup = require('./dbCleanup.js').dbCleanup;

function _beforeClean(done) {
    dbCleanup().then(done).catch(done);
}

exports.beforeCleanup = _beforeClean;

示例(我只更改了 dbCleanup.js 以使用另一个承诺)

dbCleanup.js

function dbCleanup() {

    return new Promise(function (resolve, reject) {
        setTimeout(resolve, 2000);
    });

}

exports.dbCleanup = dbCleanup;

globalBefore.js

var dbCleanup = require('./dbCleanup.js').dbCleanup;

function _beforeClean(done) {
    dbCleanup().then(done).catch(done);
}

exports.beforeCleanup = _beforeClean;

index.js

var globalBefore = require("../globalBefore.js");

describe("POST /employees/", function () {

    this.timeout(5000); // because the promise take 2000ms

    console.log("clearing db tables...")
    before(function (done) {
        console.log('before calling beforeCleanup');
        globalBefore.beforeCleanup(function () {
            console.log('after calling beforeCleanup');
            done(); // done cleaning db
        });
    });

    /* Without the console.logs
    console.log("clearing db tables...");
    before(globalBefore.beforeCleanup)
    */

    beforeEach(function (done) {
        // ... do some business logic related work here ...
        console.log('beforeEach');
        done();
    });


    it.only('Try create an employee', function (done) {
        // ... API call to create an employee and use Chai assertions to validate ...
        console.log('it');
        done();
    });
});

输出

clearing db tables...

  POST /employees/
before calling beforeCleanup
after calling beforeCleanup
beforeEach
it
    √ Try create an employee


  1 passing (2s)

https://mochajs.org/#hooks