node.js - "before all"钩子(Hook)随机出现在我的测试中

标签 node.js automated-tests mocha.js chai

我目前正在运行一个由 Express 和 MongoClient 以及 Mocha 和 Chai 组成的堆栈进行测试。我正在为我的端点编写测试用例,但时不时会出现一个随机错误。下面是我正在写的一套西装的片段:

describe('Recipes with populated database', () => {
    before((done) => {
    var recipe1 = {"search_name": "mikes_mac_and_cheese", "text_friendly_name": "Mikes Mac and Cheese","ingredients": [{"name": "elbow_noodles","text_friendly_name": "elbow noodles","quantity": 12,"measurement": "oz"},{"name": "cheddar_cheese","text_friendly_name": "cheddar cheese","quantity": 6,"measurement": "oz"},{"name": "gouda_cheese","text_friendly_name": "gouda cheese","quantity": 6,"measurement": "oz"},{"name": "milk","text_friendly_name": "milk","quantity": 2,"measurement": "oz"}],"steps": ["Bring water to a boil","Cook noodels until al dente.","Add the milk and cheeses and melt down.","Stir constantly to ensure even coating and serve."],"course": ["dinner","lunch","side"],"prep_time": {"minutes": 15,"hours": 0},"cook_time":{"minutes": 25,"hours": 1},"cuisine": "italian","submitted_by": "User1","searchable": true};

    db.collectionExists('recipes').then((exists) => {
        if (exists) {
            db.getDb().dropCollection('recipes', (err, results) => {
             if (err)
             {
                throw err;
             }
            });
        }

        db.getDb().createCollection('recipes', (err, results) => {
            if (err)
            {
                throw err;
            }
        });

        db.getDb().collection('recipes').insertOne(recipe1, (err, result) => {
            done();
        });
    });
});

collectionExists() 方法仅接受一个名称并返回一个解析为 true/false 值的 Promise。我已经做了一些调试并且工作得很好。当我点击调用 createCollection 的代码部分时,我遇到了问题。我收到关于集合如何已存在的错误,从而导致我的测试失败。我每三次运行测试时似乎都会发生这种情况。

所有这一切的目的是确保在开始测试之前,名为 recipes 的数据库集合完全为空,这样我就不会陷入旧数据或处于不受控制的环境中。

最佳答案

.createCollection.insertOne 之间存在竞争条件。换句话说,它们同时开始并并行进行。没有办法知道哪一个将首先完成。

.insert 在 MongoDB 中的工作方式是,如果集合丢失并且您尝试插入 - 它将创建一个集合。因此,如果首先执行 .insertOne - 集合就会创建,这就是为什么您在尝试 createCollection 时收到 已经存在 错误的原因。

由于数据库调用的异步性质,您必须将后续调用放在上一个调用的回调中。一。这样就不会出现并行执行:

before((done) => {
    var recipe1 = {/**/};

    db.collectionExists('recipes')
        .then((exists) => {
            if (exists) {
                // Drop the collection if it exists.
                db.getDb().dropCollection('recipes', (err) => {
                    if (err) {
                        // If there's an error we want to pass it up to before.
                        done(err);
                        return;
                    }

                    // Just insert a first document into a non-existent collection.
                    // It's going to be created.
                    // Notice the done callback.
                    db.getDb().collection('recipes').insertOne(recipe1, done);
                });
            }

            // If there were no such collection - simply insert the first doc to create it.
            // Note that I'm passing before's done callback inside.
            db.getDb().collection('recipes').insertOne(recipe1, done);
        })
        // We don't want to lose the error from this promise always.
        .catch(err => done(err));
});

但是。实际上,每次运行测试时都不需要删除并重新创建集合。您可以简单地 .remove before block 中的所有对象。所以正确的解决方案可能是:

before((done) => {
    var recipe1 = {/**/};

    const recipes = db.getDb().collection('recipes');

    // Simply wipe out the data
    recipes.remove({}, err => {
        if (err) {
            done(err);
            return;
        }

        recipes.insertOne(recipe1, done);
    });
});

关于node.js - "before all"钩子(Hook)随机出现在我的测试中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50813300/

相关文章:

node.js - 如何从 Controller /EJS访问应用程序? Express.js

javascript - Mocha 不会在 after() 函数中调用 rmdir

java - 无法使用 Selenium 和 Java 单击 Flipkart 主页中图像 slider 中的图像之一

automated-tests - QTP-获取元素的值

testing - TestCafe:无法单击 onlclick 操作菜单项

javascript - Sails.js:如何实际运行测试

javascript - Nightmare.js中的.type和.click选择器

javascript - 因为 if 无法中断 for 循环?

node.js - Heroku dynos 不共享文件系统

node.js - Sequelize,如何使用 Op.contains 找到具有特定值的模型