крючок «прежде всего», случайно отображаемый в моих тестах - PullRequest
0 голосов
/ 12 июня 2018

В настоящее время я использую для тестирования стек, состоящий из 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.Я уже сделал некоторую отладку, и она работает просто отлично.Проблема в том, что я попадаю в раздел кода, где я звоню createCollection.Я получаю сообщение о том, что коллекция уже существует, что приводит к сбою моих тестов.Похоже, это происходит каждый третий раз, когда я запускаю свои тесты.

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

1 Ответ

0 голосов
/ 12 июня 2018

Состояние вашей гонки между .createCollection и .insertOne.Другими словами, они запускаются одновременно и идут параллельно.Невозможно определить, что будет сделано в первую очередь.

Способ, которым .insert работает в MongoDB, заключается в том, что если коллекция отсутствует и вы пытаетесь вставить - она ​​собирается создать коллекцию.Таким образом, если .insertOne выполняется первым - коллекция создается, и поэтому вы получаете ошибку already exists при попытке 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.Поэтому, вероятно, правильное решение будет:

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);
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...