Автор оригинала: 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