Рубрики
Без рубрики

Ускорить тесты вашего монгодб в узле

Узнайте, как ускорить тестовые люксы Node.js Mongodb, динамически создавая экземпляры базы данных в памяти.

Автор оригинала: David Weldon.

У вас есть пара выбора, когда речь идет о тестах Backend, которые взаимодействуют с Mongo: издевайтесь на звонки или запрашивайте живую базу данных. Первый имеет серьезное недостатком потенциальной неточности (например, в ваших селекторах могут быть опечатки). Последнее может быть непрактично медленно при запуске большого количества тестов.

Лучшее решение, которое я нашел, это программно раскрутит в памяти Реальный монгодб экземпляр Для каждой группы испытаний, используя mongodb-memory-server упаковка.

npm i -D mongodb-memory-server

В качестве альтернативы, если вы хотите поделиться одним и тем же двоичным MongoDB для всех ваших проектов (это то, что я предпочитаю) Вы можете запустить:

npm i -D mongodb-memory-server-global

Если вы прочитали через Документы , вы сможете увидеть, что это работает в многочисленных средах тестирования, а также с выходящим нами, как мангуст Отказ Кроме того, он будет загружать необходимую Mongodb Binary для вас, поэтому нет необходимой внешней настройки.

В оставшейся части этой статьи я объясню, как я использую mongodb-memory-server вместе с Родной водитель MongoDB Отказ Наконец, мы будем завернуть простым Jest пример.

Вот моя реализация класса под названием Dbmanager которые инкапсулиты все функции настройки и разрыва DB:

const { MongoClient } = require('mongodb');
const { MongoMemoryServer } = require('mongodb-memory-server-global');

// Extend the default timeout so MongoDB binaries can download
jest.setTimeout(60000);

// List all of your collection names here - I'll add some examples
const COLLECTIONS = ['users', 'groups', 'comments'];

class DBManager {
  constructor() {
    this.db = null;
    this.server = new MongoMemoryServer();
    this.connection = null;
  }

  // Spin up a new in-memory mongo instance
  async start() {
    const url = await this.server.getUri();
    this.connection = await MongoClient.connect(url, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    });
    this.db = this.connection.db(await this.server.getDbName());
  }

  // Close the connection and halt the mongo instance
  stop() {
    this.connection.close();
    return this.server.stop();
  }

  // Remove all documents from the entire database - useful between tests
  cleanup() {
    return Promise.all(COLLECTIONS.map((c) => this.db.collection(c).deleteMany({})));
  }
}

module.exports = DBManager;

И вот простая шутка для испытаний, используя Dbmanager пример:

const DBManager = require('./DBManager');

const GROUP = { _id: 'g1', createdAt: new Date() };

describe('Group.getGroupById', () => {
  const dbman = new DBManager();

  afterAll(() => dbman.stop());
  beforeAll(() => dbman.start());
  afterEach(() => dbman.cleanup());
  beforeEach(() => dbman.models.Group.collection.insertOne(GROUP));

  it('should return null with an invalid id', async () => {
    expect.assertions(1);
    const result = await dbman.models.Group.getGroupById('x');
    expect(result).toBeNull();
  });

  it('should return a group with a valid id', async () => {
    expect.assertions(1);
    const result = await dbman.models.Group.getGroupById(GROUP._id);
    expect(result).toEqual(GROUP);
  });
});

Детали тестов не так важны, но обратите внимание, как мы раскрутим экземпляр MongoDB в начале тестового блока с BeForall , а затем остановите его в конце тестового блока с Послеобеда Отказ Для каждого теста в блоке мы сохраняем одну и ту же базу данных, но удалите все его содержимое с помощью dbman.cleanup () Отказ Это гарантирует, что каждый тест работает в чистой среде.

Примечание. Вышеуказанное реализация требует, чтобы все доступные коллекции перечислены в Коллекции множество. Более сложный подход будет запрашивать базу данных для всех коллекций во время удаления. Есть пакеты, которые делают именно это.

На момент написания этого письма у меня есть 712 тесты на бэкэндов (98% из которых требуют базы данных), а полное время выполнения – 64,7 секунды На моем старении I5-2400.

Наслаждайтесь увеличением скорости!

Фото Вери Иванова на Unsplash