使用模拟器测试Firestore规则时如何设置测试数据? [英] How to setup test data when testing Firestore Rules with Emulator?
问题描述
我正在使用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屋!