Как настроить firebase firestore и облачный тестовый набор функций для разработки JS - PullRequest
2 голосов
/ 21 мая 2019

Согласно следующей записи Google I / O (2019) команды Firebase, новый эмулятор позволяет нам комбинировать Firebase / базу данных и облачную функцию для полной имитации наших кодов сервера FireBase. Это также должно означать, что мы сможем написать тесты для него.

мы выпускаем новый эмулятор Cloud Functions, который также может общаться с эмулятором Cloud Firestore. Так что если вы хотите построить функция, которая запускается при обновлении и записи документа Firestore данные обратно в базу данных вы можете кодировать и тестировать весь этот поток локально на вашем ноутбуке (Источник: Запись в блоге Firebase )

Я могу найти несколько ресурсов, которые ищут / описывают каждую отдельную симуляцию, но не все вместе

  1. Функция облачного тестирования модулей
  2. Эмуляция записи в базу данных
  3. Эмуляция записи в Firestore

1 Ответ

4 голосов
/ 21 мая 2019

Чтобы настроить тестовую среду для облачной функции, которая позволяет вам моделировать чтение / запись и настроить тестовые данные, вы должны сделать следующее.

Предпосылки

Я предполагаю, что на данный момент у вас настроен проект firebase с папкой функций и index.js. Позже тесты будут в папке functions/test. Если у вас нет настройки проекта, используйте firebase init для настройки проекта.

Зависимости установки

Сначала добавьте / установите следующие зависимости: mocha, @firebase/testing, firebase-functions-test, firebase-functions, firebase-admin, firebase-tools

Инициализация и запуск эмуляторов

  1. База данных инициализации firebase setup:emulators:database
  2. Инициативный пожарный магазин firebase setup:emulators:firestore
  3. Запустите эмуляторы с firebase emulators:start

На данный момент у вас должны быть запущены эмуляторы базы данных и firestore. Теперь мы можем читать / писать в него.

index.js для примера облачной функции

// functions/index.js

const fbInit = require("./ainitFb");
let admin = fbInit.getAdmin();

const functions = require("firebase-functions");

exports.addCrewMemeber = functions.firestore
    .document("characters/{characterId}")
    .onCreate(async (characterSnap, context) => {
        const heartOfGold = admin
            .firestore()
            .collection("spaceShip")
            .doc("Heart-of-Gold");

        const heartData = (await heartOfGold.get()).data();

        await heartOfGold.set({
            crew: [...heartData.crew, context.params.characterId],
            crewCount: heartData.crewCount + 1,
        });

        // Update the characters to be in space
        return characterSnap.ref.update({ inSpace: true });
    });

Вы видите, что я не импортирую admin напрямую из firebase-admin. Но вместо require("./ainitFb"). Я делаю это потому, что нам нужно заглушить администратора, с нашим новым администратором, указывающим на эмулятор.

Создайте модуль firebase-admin, чтобы разрешить насмешку над firebase-admin

// functions/aniniFb.js

exports.initializeMockApp = function(mock) {
    admin = mock;
};

exports.initializeApp = function() {
    if (!admin) {
        admin = require("firebase-admin");
        admin.initializeApp();
    }
};

exports.getAdmin = function() {
    return global.admin;
};

exports.admin = (inneradmin => {
    return inneradmin;
})(
    global.admin,
);

тестовый файл мокко test.js

// functions/test/test.js


const assert = require("assert");
const projectId = "dummy";
const firebase = require("@firebase/testing");
const admin = firebase.initializeAdminApp({ projectId, databaseName: projectId });
const test = require("firebase-functions-test")({ projectId, databaseName: projectId });
const fbInit = require("../ainitFb");
// this will inject the mocked admin
fbInit.initializeMockApp(admin);

// load this only after you ran 'initializeMockApp'
const myFunctions = require("../index.js");

// Create a simple document snapshot
// I did that because currently using test.firestore.makeDocumentSnapshot() is not working
// For some reasons it says the firebase db can't be reached, while it's actually running
function makeDocumentSnapshot(data, ref) {
    return {
        id: ref.id,
        data: () => data,
        ref,
    };
}

beforeEach(async function() {
    // we remove the timeout as the default is 2sec which is often too short to also start the emulators
    this.timeout(0);
    // Clear the database between tests
    await firebase.clearFirestoreData({ projectId });
});

it("Add Crew Members", async function() {
    this.timeout(0);

    const heartOfGold = admin
        .firestore()
        .collection("spaceShip")
        .doc("Heart-of-Gold");

    const trillianRef = admin
        .firestore()
        .collection("characters")
        .doc("Trillian");

    // init crew members of the Heart of Gold
    await heartOfGold.set({
        crew: [],
        crewCount: 0,
    });

    // save the character Trillian to the DB
    const trillianData = { name: "Trillian", inSpace: false };
    await trillianRef.set(trillianData);

    // Add Trillian to the Heart of Gold
    const trillianSnap = makeDocumentSnapshot(trillianData, trillianRef);
    const addCrewMemeber = test.wrap(myFunctions.addCrewMemeber);
    await addCrewMemeber(trillianSnap, { params: { characterId: "Trillian" } });

    // check if the crew size has change
    const heart = await heartOfGold.get();
    const trillian = await trillianRef.get();

    // at this point the Heart of Gold has one crew member and trillian is in space 
    assert.deepStrictEqual(heart.data().crewCount, 1, "Crew Members");
    assert.deepStrictEqual(trillian.data().inSpace, true, "In Space");
});


запустить тест

Для запуска теста мы можем просто запустить mocha с mocha, если он установлен глобально, или yarn mocha, если локально установлен через yarn.

Если все это работает, вы должны увидеть следующий вывод

  √ Add Crew Members (189ms)

  1 passing (223ms)

Запуск его в системе CI

Чтобы запустить тот же код в системе CI, вы должны убедиться, что эмуляторы запущены, прежде чем вы сможете запустить тест. Это можно просто сделать с помощью команды firebase emulators:exec. Например, вот так firebase emulators:exec "mocha --exit". Не забудьте --exit, иначе мокко может не закончиться, и ваш CI-runner не остановится. Кроме того, если у вас возникают проблемы с запуском / запуском теста или эмулятора, возможно, вы инициализировали их в неправильной папке. Я пользуюсь этим yarn firebase emulators:exec --only database,firestore "yarn mocha functions --exit", чтобы исправить проблему, при которой мокко выглядит не в той папке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...