Firestore安全规则中exists()函数无法检测到已存在文档的问题
问题原因及解决方案
核心问题:测试中的异步操作未正确等待
你在测试代码中调用testUserDoc.set()时没有等待异步操作完成,导致后续执行assertSucceeds(testFollowersDoc.set(...))时,users/user1文档还未被写入到模拟Firestore中,安全规则里的exists()自然返回false。
修复步骤
确保用户文档创建完成后再执行后续操作
在测试代码中添加await等待set()操作完成:const database = testEnv.authenticatedContext('user1').firestore(); const testFollowersDoc = database.collection("followers").doc("user1"); const testUserDoc = database.collection("users").doc("user1"); // 等待用户文档创建完成 await testUserDoc.set({about: "Wow", following: []}); // 再执行followers文档的创建操作 await assertSucceeds(testFollowersDoc.set({followers: []}));验证安全规则逻辑(可选)
你的安全规则逻辑本身是正确的,但可以再确认$(database)变量的引用——在Firestore安全规则中,$(database)会自动解析为当前数据库的名称,默认场景下无需修改。如果是多数据库场景,需要确保路径匹配,但你的场景中应该不存在这个问题。测试断言的正确写法
建议使用await直接调用assertSucceeds/assertFails,而不是通过expect(...).resolves,这样代码更直观且不易出错:// 测试无用户文档时创建失败 await assertFails(testFollowersDoc.set({followers: []})); // 创建用户文档后测试成功 await testUserDoc.set({about: "Wow", following: []}); await assertSucceeds(testFollowersDoc.set({followers: []}));
额外注意事项
- 使用
@firebase/rules-unit-testing时,所有模拟Firestore的写入、读取操作都是异步的,必须通过await等待操作完成,否则模拟数据库的状态不会更新。 - 可以在创建用户文档后,先执行一次读取操作验证文档存在,再测试followers的创建:
const userDocSnapshot = await testUserDoc.get(); console.log(userDocSnapshot.exists); // 应输出true
内容的提问来源于stack exchange,提问作者Saurav
相关产品推荐
相关产品推荐

