使用模拟器测试Firestore规则时如何设置测试数据? [英] How to setup test data when testing Firestore Rules with Emulator?

查看:92
本文介绍了使用模拟器测试Firestore规则时如何设置测试数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用mocha和Firestore 仿真器进行Cloud Firestore规则的测试,问题是如何在运行测试之前初始化一些测试数据?

I am working on tests for Cloud Firestore Rules, using mocha and Firestore Emulator, and the question is how to initialize some test data before running tests?

要测试我的规则,我首先需要初始化一些测试数据.问题是,在使用仿真器时,我无法将任何数据放入文档中,文档只有id. 在文档,所以我尝试同时使用 makeDocumentSnapshot中的makeDocumentSnapshot,以及通过 admin应用创建的文档,该应用使用initializeAdminApp创建.

To test my rules, I first need to initialize some test data. The problem is that I cannot put any data into a document when working with Emulator, documents only have id. I didn't find any example of setting up test data for Rules tests in the docs, so I tried to use both makeDocumentSnapshot from @firebase/testing and document creation via admin app created with initializeAdminApp.

用例:

要访问/objects/{object_id}上的文档,必须认证用户并具有read权限:get('/objects/{object_id}/users/{$(request.auth.uid)}').data.read == true.另外,object必须可用:get('/objects/{object_id}').data.available == true.

To get access to a document at /objects/{object_id}, a User must be authenticated and have read permission: get('/objects/{object_id}/users/{$(request.auth.uid)}').data.read == true. Also, object must be available: get('/objects/{object_id}').data.available == true.

因此,要测试我的规则,我需要一些具有用户权限的预设测试数据.

So, to test my rules I need some preset test data with User permissions.

预期的数据库结构:

objects collection:
  object_id: {
    // document fields:
    available (bool)

    // nested collection:
    users collection: {
      user_id: {
        // document fields:
        read (bool)
      }
    }
  }

我的规则示例:

service cloud.firestore {
  match /databases/{database}/documents {
    match /objects/{object} {
      function objectAvailable() {
        return resource.data.available;
      }
      // User has read access.
      function userCanReadObject() {
        return get(/databases/$(database)/documents/objects/$(object)/users/$(request.auth.uid)).data.read == true;
      }
      // Objects Permission Rules
      allow read: if objectAvailable() && userCanReadObject();
      allow write: if false;

      // Access forbidden. Used for permission rules only.
      match /users/{document=**} {
        allow read, write: if false;
      }
    }
  }
}

我的测试示例:

const firebase = require('@firebase/testing');
const fs = require('fs');

// Load Firestore rules from file
const firestoreRules = fs.readFileSync('../firestore.rules', 'utf8');
const projectId = 'test-application';
const test = require('firebase-functions-test')({ projectId, databaseName: projectId });

describe('Tests for Rules', () => {
  let adminApp;

  const testData = {
    myObj: {
      id: 'test',
      data: {
        available: true,
      },
    },
    alice: {
      id: 1,
      data: {
        read: true,
      },
    },
  };

  before(async () => {
    // Load Rules
    await firebase.loadFirestoreRules({ projectId,  rules: firestoreRules });

    // Initialize admin app.
    adminApp = firebase.initializeAdminApp({ projectId }).firestore();

    // Create test data
    await adminApp.doc(`objects/${testData.myObj.id}`).set(testData.myObj.data);
    await adminApp
      .doc(`objects/${testData.myObj.id}/users/${testData.alice.id}`)
      .set(testData.alice.data);

    // Create test data with  `firebase-functions-test`
    // test.firestore.makeDocumentSnapshot(testData.myObj.data, `objects/${testData.myObj.id}`);
    // test.firestore.makeDocumentSnapshot(
    //   testData.alice.data,
    //   `objects/${testData.myObj.id}/users/${testData.alice.id}`,
    // );
  });

  beforeEach(async () => {
    await firebase.clearFirestoreData({ projectId });
  });

  after(async () => {
    // Shut down all testing Firestore applications after testing is done.
    await Promise.all(firebase.apps().map(app => app.delete()));
  });

  describe('Testing', () => {
    it('User with permission can read objects data', async () => {
      const db = firebase
        .initializeTestApp({ projectId, auth: { uid: testData.alice.id } })
        .firestore();
      const testObj = db.doc(`objects/${testData.myObj.id}`);

      await firebase.assertSucceeds(testObj.get());
    });
  });
});

控制台输出以进行测试运行:

Console output for test run:

1) User with permission can read objects data
0 passing (206ms)
1 failing
1) Tests for Rules
 Testing
   User with permission can read objects data:
FirebaseError: 
false for 'get' @ L53

要检查创建的测试数据,我在await firebase.assertSucceeds(testObj.get());行之前添加了以下代码:

To check created test data I added the following code before await firebase.assertSucceeds(testObj.get()); line:

const o = await adminApp.doc(`objects/${testData.myObj.id}`).get();
const u = await adminApp.doc(`objects/${testData.myObj.id}/users/${testData.alice.id}`).get();
console.log('obj data: ', o.id, o.data());
console.log('user data: ', u.id, u.data());

输出如下:

obj data:  test undefined
user data:  1 undefined

我还试图从beforeEach中删除代码,结果是相同的.

I also tried to remove the code from beforeEach, the result is the same.

推荐答案

您可以使用initializeAdminApp获取管理员特权(允许所有操作):

You can use initializeAdminApp to get admin privilegies (all operations are allowed):


    const dbAdmin = firebase.initializeAdminApp({projectId}).firestore();

    // Write mock documents
    if (data) {
        for (const key in data) {
            if (data.hasOwnProperty(key)) {
                const ref = dbAdmin.doc(key);
                await ref.set(data[key]);
            }
        }
    }

数据应具有以下格式:

  data = {
    'user/alice': {
      name:'Alice'
    },
    'user/bob': {
      name:'Bob'
    },
  };

这篇关于使用模拟器测试Firestore规则时如何设置测试数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆