如何将Firestore模拟器导入的数据注入数据库实例

时间:2020-07-22 21:01:47

标签: firebase unit-testing google-cloud-firestore firebase-tools

我知道我们现在可以export and import data使用Firestore模拟器。

一个人如何在单元测试环境中访问导入的数据?也就是说,在使用@firebase/testing时,我们通常会像这样创建测试应用:

const db = firebase.initializeTestApp({ projectId: PROJECT_ID, auth}).firestore(); 

如何访问通过仿真器导入的数据并将其馈送到该数据库实例?

我的用例是针对导入的数据在firestore规则上运行单元测试(作为参考,所需的设置与此其他related question非常相似,但是我不是依赖于手动构建的模拟对象,而是d想使用来自仿真器导出/导入功能的数据)

这是我的测试文件

/**
 * unit tests for firestore security and data validation rules
 *
 * adapted from https://github.com/firebase/quickstart-testing/blob/master/unit-test-security-rules
 */
const firebase = require("@firebase/testing");
const fs = require("fs");
const path = require("path")

/**
 * The emulator will accept any project ID for testing.
 */
const PROJECT_ID = "test-dev-project";

/**
 * The FIRESTORE_EMULATOR_HOST environment variable is set automatically
 * by "firebase emulators:exec"
 */
const COVERAGE_URL = `http://${process.env.FIRESTORE_EMULATOR_HOST}/emulator/v1/projects/${PROJECT_ID}:ruleCoverage.html`;

/**
 * Set up mock data
 */
const mockUser = {
  uid: 'alice',
  email: 'alice@example.com',
  company: 'testCompany'
}

/**
 * Creates a new client FirebaseApp with authentication and returns the Firestore db instance.
 * @param {object} auth the object to use for authentication (typically {uid: some-uid})
 * @param {object} data the test data to use for filling the db
 * @return {object} the firestore instance db .
 */
getAuthedDb = async (auth, data) => {
  // initialize test app
  const app = firebase.initializeTestApp({ projectId: PROJECT_ID, auth });
  let db = app.firestore();
  return db;
};

beforeEach(async () => {
  // Clear the database between tests
  await firebase.clearFirestoreData({ projectId: PROJECT_ID });
});

before(async () => {
  // Load the rules file before the tests begin
  const rules = fs.readFileSync("firestore.rules", "utf8");
  await firebase.loadFirestoreRules({ projectId: PROJECT_ID, rules });
});

after(async () => {
  // Delete all the FirebaseApp instances created during testing
  // Note: this does not affect or clear any data
  await Promise.all(firebase.apps().map((app) => app.delete()));
  console.log(`View rule coverage information at ${COVERAGE_URL}\n`);
});

function printDoc(doc) {
  if (doc.exists) {
      console.log(`Document ${doc.id} data:`, doc.data());
  } else {
      // doc.data() will be undefined in this case
      console.log(`No such document: ${doc.ref.path}, parent: ${doc.ref.parent.id}`);
  }
}

describe("Test Security Rules", () => {
  it("fetches data imported from emulator", async () => {
    const db = await getAuthedDb({uid: 'abcd'});
    const ref = db.doc("testdata/ac7yWTZekvGJMQj6Zq3M");
    await firebase.assertSucceeds(ref.get().then(printDoc));
  });
});

当我运行firebase emulators:exec --only firestore --import=data/ "yarn run test-rules"test-rules映射到mocha --timeout 10000 test/test.spec.js)时,断言成功,但未找到文档"testdata/ac7yWTZekvGJMQj6Zq3M",但它存在于我想要的数据中从data/

导入

1 个答案:

答案 0 :(得分:0)

原来这是问题所在

beforeEach(async () => {
  // Clear the database between tests
  await firebase.clearFirestoreData({ projectId: PROJECT_ID });
});

在执行每个测试之前,它将完全清除模拟器数据。我的大错误是,解决方案是完全删除该代码,因为我的测试数据不需要在测试用例之间进行更改