ขณะสร้างแอป คุณอาจต้องการล็อกการเข้าถึงฐานข้อมูล Cloud Firestore อย่างไรก็ตาม ก่อนที่จะเปิดตัว คุณจะต้องมี Cloud Firestore Security Rulesที่ละเอียดยิ่งขึ้น โปรแกรมจำลอง Cloud Firestore ช่วยให้คุณเขียนการทดสอบ 1 หน่วยที่ตรวจสอบลักษณะการทำงานของ Cloud Firestore Security Rules ได้ นอกเหนือจากการสร้างต้นแบบ และทดสอบฟีเจอร์และลักษณะการทำงานทั่วไปของแอป
คู่มือเริ่มใช้งานฉบับย่อ
ลองใช้ตัวอย่างคู่มือเริ่มใช้งานฉบับย่อสำหรับกรณีทดสอบพื้นฐาน 2-3 กรณีที่มีกฎง่ายๆ
ทำความเข้าใจ Cloud Firestore Security Rules
ใช้ Firebase Authentication และ Cloud Firestore Security Rules สำหรับการตรวจสอบสิทธิ์ การให้สิทธิ์ และการตรวจสอบข้อมูลแบบ Serverless เมื่อใช้ไลบรารีของไคลเอ็นต์อุปกรณ์เคลื่อนที่และเว็บ
Cloud Firestore Security Rules ประกอบด้วย 2 ส่วน ได้แก่
- คำสั่ง
matchที่ระบุเอกสารในฐานข้อมูล - นิพจน์
allowที่ควบคุมการเข้าถึงเอกสารเหล่านั้น
Firebase Authentication จะยืนยันข้อมูลเข้าสู่ระบบของผู้ใช้และเป็นพื้นฐานสำหรับ ระบบการเข้าถึงตามผู้ใช้และตามบทบาท
ระบบจะประเมินคำขอฐานข้อมูลแต่ละรายการจากไลบรารีของไคลเอ็นต์สำหรับอุปกรณ์เคลื่อนที่/เว็บ Cloud Firestore เทียบกับกฎความปลอดภัยก่อนที่จะอ่านหรือเขียนข้อมูลใดๆ หากกฎปฏิเสธการเข้าถึงเส้นทางเอกสารที่ระบุไว้ คำขอทั้งหมดจะไม่สำเร็จ
ดูข้อมูลเพิ่มเติมเกี่ยวกับ Cloud Firestore Security Rules ได้ที่หัวข้อ เริ่มต้นใช้งาน Cloud Firestore Security Rules
ติดตั้งโปรแกรมจำลอง
หากต้องการติดตั้งโปรแกรมจำลอง Cloud Firestore ให้ใช้ Firebase CLI และเรียกใช้คำสั่งด้านล่าง
firebase setup:emulators:firestore
เรียกใช้โปรแกรมจำลอง
เริ่มต้นด้วยการเริ่มต้นโปรเจ็กต์ Firebase ในไดเรกทอรีงาน ซึ่งเป็นขั้นตอนแรกที่พบบ่อยเมื่อใช้ Firebase CLI
firebase init
เริ่มโปรแกรมจำลองโดยใช้คำสั่งต่อไปนี้ โปรแกรมจำลองจะทำงานต่อไปจนกว่าคุณจะหยุดกระบวนการ
firebase emulators:start --only firestore
ในหลายกรณี คุณอาจต้องการเริ่มโปรแกรมจำลอง เรียกใช้ชุดการทดสอบ แล้วปิดโปรแกรมจำลองหลังจากที่การทดสอบทำงานเสร็จแล้ว คุณทำเช่นนี้ได้อย่างง่ายดายโดยใช้คำสั่ง emulators:exec
firebase emulators:exec --only firestore "./my-test-script.sh"
เมื่อเริ่มต้น โปรแกรมจำลองจะพยายามทำงานในพอร์ตเริ่มต้น (8080) คุณสามารถ
เปลี่ยนพอร์ตของโปรแกรมจำลองได้โดยแก้ไขส่วน "emulators" ของไฟล์
firebase.json
{
// ...
"emulators": {
"firestore": {
"port": "YOUR_PORT"
}
}
}สิ่งที่ควรทราบก่อนเรียกใช้โปรแกรมจำลอง
โปรดคำนึงถึงสิ่งต่อไปนี้ก่อนที่จะเริ่มใช้โปรแกรมจำลอง
- โปรแกรมจำลองจะโหลดกฎที่ระบุไว้ในช่อง
firestore.rulesของไฟล์firebase.jsonในตอนแรก โดยจะคาดหวังชื่อไฟล์ในเครื่องที่มีCloud Firestore Security Rulesและใช้กฎเหล่านั้นกับทุกโปร101}เจ็กต์ หากคุณไม่ระบุเส้นทางไฟล์ในเครื่องหรือใช้เมธอดloadFirestoreRulesตามที่อธิบายไว้ด้านล่าง โปรแกรมจำลองจะถือว่าทุกโปรเจ็กต์มีกฎแบบเปิด - แม้ว่า
Firebase SDK ส่วนใหญ่
จะทำงานร่วมกับโปรแกรมจำลองได้โดยตรง แต่มีเพียงไลบรารี
@firebase/rules-unit-testingเท่านั้นที่รองรับ การจำลองauthในกฎความปลอดภัย ซึ่งทำให้การทดสอบ 1 หน่วยง่ายขึ้นมาก นอกจากนี้ ไลบรารียังรองรับฟีเจอร์เฉพาะของโปรแกรมจำลองบางอย่าง เช่น การล้างข้อมูลทั้งหมด ตามที่ระบุไว้ด้านล่าง - นอกจากนี้ โปรแกรมจำลองยังยอมรับโทเค็นการตรวจสอบสิทธิ์ Firebase สำหรับเวอร์ชันที่ใช้งานจริงที่ระบุผ่าน Client SDK และประเมินกฎตามนั้น ซึ่งช่วยให้คุณเชื่อมต่อแอปพลิเคชันกับโปรแกรมจำลองได้โดยตรงในการทดสอบการผสานรวมและการทดสอบด้วยตนเอง
เรียกใช้การทดสอบ 1 หน่วยในเครื่อง
เรียกใช้การทดสอบ 1 หน่วยในเครื่องด้วย JavaScript SDK v9
Firebase จัดจำหน่ายไลบรารีการทำ Unit Test สำหรับกฎความปลอดภัยพร้อมกับ JavaScript SDK เวอร์ชัน 9 และ SDK เวอร์ชัน 8 โดย API ของไลบรารีจะแตกต่างกันอย่างมาก เราขอแนะนำไลบรารีการทดสอบ v9 ซึ่งมีประสิทธิภาพมากขึ้นและต้องมีการตั้งค่าน้อยลงเพื่อเชื่อมต่อกับโปรแกรมจำลอง จึงช่วยหลีกเลี่ยงการใช้ทรัพยากรเวอร์ชันที่ใช้งานจริงโดยไม่ได้ตั้งใจได้อย่างปลอดภัย เราจะยังคงให้บริการ ไลบรารีการทดสอบ v8 ต่อไปเพื่อความเข้ากันได้แบบย้อนกลับ
ใช้โมดูล @firebase/rules-unit-testing เพื่อโต้ตอบกับโปรแกรมจำลองที่ทำงานในเครื่อง หากคุณพบข้อผิดพลาดการหมดเวลาหรือ ECONNREFUSED ให้ตรวจสอบอีกครั้งว่าโปรแกรมจำลองกำลังทำงานอยู่จริง
เราขอแนะนำอย่างยิ่งให้ใช้ Node.js เวอร์ชันล่าสุดเพื่อให้คุณใช้สัญกรณ์ async/await ได้ ลักษณะการทำงานเกือบทั้งหมดที่คุณอาจต้องการทดสอบเกี่ยวข้องกับฟังก์ชันแบบอะซิงโครนัส และโมดูลการทดสอบได้รับการออกแบบมาให้ทำงานร่วมกับโค้ดที่อิงตาม Promise
ไลบรารีการทดสอบ 1 หน่วยสำหรับกฎ v9 จะทราบถึงโปรแกรมจำลองอยู่เสมอและจะไม่แตะต้องทรัพยากรเวอร์ชันที่ใช้งานจริง
คุณนำเข้าไลบรารีโดยใช้คำสั่งนำเข้าแบบแยกส่วน v9 เช่น
import {
assertFails,
assertSucceeds,
initializeTestEnvironment
} from "@firebase/rules-unit-testing"
// Use `const { … } = require("@firebase/rules-unit-testing")` if imports are not supported
// Or we suggest `const testing = require("@firebase/rules-unit-testing")` if necessary.
เมื่อนำเข้าแล้ว การใช้การทดสอบ 1 หน่วยจะเกี่ยวข้องกับสิ่งต่อไปนี้
- สร้างและกำหนดค่า
RulesTestEnvironmentด้วยการเรียกinitializeTestEnvironment - ตั้งค่าข้อมูลทดสอบโดยไม่ทริกเกอร์กฎโดยใช้วิธีที่สะดวกซึ่งช่วยให้คุณข้ามกฎได้ชั่วคราว นั่นคือ
RulesTestEnvironment.withSecurityRulesDisabled - ตั้งค่าชุดการทดสอบและฮุกก่อน/หลังการทดสอบแต่ละรายการด้วยการเรียกเพื่อล้างข้อมูลทดสอบและสภาพแวดล้อม เช่น
RulesTestEnvironment.cleanup()หรือRulesTestEnvironment.clearFirestore() - ใช้กรณีทดสอบที่เลียนแบบสถานะการตรวจสอบสิทธิ์โดยใช้
RulesTestEnvironment.authenticatedContextและRulesTestEnvironment.unauthenticatedContext
เมธอดและฟังก์ชันยูทิลิตีทั่วไป
ดูเมธอดการทดสอบเฉพาะของโปรแกรมจำลองใน SDK v9 ด้วย
initializeTestEnvironment() => RulesTestEnvironment
ฟังก์ชันนี้จะเริ่มต้นสภาพแวดล้อมการทดสอบสำหรับการทำ Unit Test สำหรับกฎ เรียกฟังก์ชันนี้ก่อนเพื่อตั้งค่าการทดสอบ การดำเนินการจะสำเร็จได้ก็ต่อเมื่อโปรแกรมจำลองกำลังทำงานอยู่
ฟังก์ชันนี้ยอมรับออบเจ็กต์ที่ไม่บังคับซึ่งกำหนด TestEnvironmentConfig ซึ่งประกอบด้วยรหัสโปรเจ็กต์และการตั้งค่าการกำหนดค่าโปรแกรมจำลอง
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
เมธอดนี้จะสร้าง RulesTestContext ซึ่งทำงานเหมือนกับผู้ใช้การตรวจสอบสิทธิ์ที่ผ่านการตรวจสอบสิทธิ์แล้ว คำขอที่สร้างผ่านบริบทที่แสดงผลจะมีโทเค็นการตรวจสอบสิทธิ์จำลองแนบอยู่ คุณจะส่งออบเจ็กต์ที่กำหนดการอ้างสิทธิ์ที่กำหนดเองหรือการลบล้างสำหรับเพย์โหลดโทเค็นการตรวจสอบสิทธิ์ก็ได้
ใช้ออบเจ็กต์บริบทการทดสอบที่แสดงผลในการทดสอบเพื่อเข้าถึงอินสแตนซ์โปรแกรมจำลองที่กำหนดค่าไว้ รวมถึงอินสแตนซ์ที่กำหนดค่าด้วย initializeTestEnvironment
// Assuming a Firestore app and the Firestore emulator for this example import { setDoc } from "firebase/firestore"; const alice = testEnv.authenticatedContext("alice", { … }); // Use the Firestore instance associated with this context await assertSucceeds(setDoc(alice.firestore().doc('/users/alice'), { ... });
RulesTestEnvironment.unauthenticatedContext() => RulesTestContext
เมธอดนี้จะสร้าง RulesTestContext ซึ่งทำงานเหมือนกับไคลเอ็นต์ที่ไม่ได้เข้าสู่ระบบผ่านการตรวจสอบสิทธิ์ คำขอที่สร้างผ่านบริบทที่แสดงผลจะไม่มีโทเค็นการตรวจสอบสิทธิ์ Firebase แนบอยู่
ใช้ออบเจ็กต์บริบทการทดสอบที่แสดงผลในการทดสอบเพื่อเข้าถึงอินสแตนซ์โปรแกรมจำลองที่กำหนดค่าไว้ รวมถึงอินสแตนซ์ที่กำหนดค่าด้วย initializeTestEnvironment
// Assuming a Cloud Storage app and the Storage emulator for this example import { getStorage, ref, deleteObject } from "firebase/storage"; const alice = testEnv.unauthenticatedContext(); // Use the Cloud Storage instance associated with this context const desertRef = ref(alice.storage(), 'images/desert.jpg'); await assertSucceeds(deleteObject(desertRef));
RulesTestEnvironment.withSecurityRulesDisabled()
เรียกใช้ฟังก์ชันการตั้งค่าการทดสอบด้วยบริบทที่ทำงานราวกับว่ากฎความปลอดภัยถูกปิดใช้
เมธอดนี้ใช้ฟังก์ชัน Callback ซึ่งใช้บริบทที่ข้ามกฎความปลอดภัยและแสดงผล Promise ระบบจะทำลายบริบทเมื่อ Promise ได้รับการแก้ไข / ปฏิเสธ
RulesTestEnvironment.cleanup()
เมธอดนี้จะทำลาย RulesTestContexts ทั้งหมดที่สร้างขึ้นในสภาพแวดล้อมการทดสอบและล้างทรัพยากรพื้นฐาน ซึ่งช่วยให้การออกจากการทดสอบเป็นไปอย่างราบรื่น
เมธอดนี้จะไม่เปลี่ยนสถานะของโปรแกรมจำลองแต่อย่างใด หากต้องการรีเซ็ตข้อมูลระหว่างการทดสอบ ให้ใช้เมธอดล้างข้อมูลเฉพาะของโปรแกรมจำลองแอปพลิเคชัน
assertSucceeds(pr: Promise<any>)) => Promise<any>
นี่คือฟังก์ชันยูทิลิตีของกรณีทดสอบ
ฟังก์ชันนี้จะยืนยันว่า Promise ที่ให้มาซึ่งครอบการดำเนินการของโปรแกรมจำลองจะได้รับการแก้ไขโดยไม่มีการละเมิดกฎความปลอดภัย
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });assertFails(pr: Promise<any>)) => Promise<any>
นี่คือฟังก์ชันยูทิลิตีของกรณีทดสอบ
ฟังก์ชันนี้จะยืนยันว่า Promise ที่ให้มาซึ่งครอบการดำเนินการของโปรแกรมจำลองจะถูกปฏิเสธเนื่องจากการละเมิดกฎความปลอดภัย
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });เมธอดเฉพาะของโปรแกรมจำลอง
ดูเมธอดการทดสอบและฟังก์ชันยูทิลิตีทั่วไปใน SDK v9 ด้วย
RulesTestEnvironment.clearFirestore() => Promise<void>
เมธอดนี้จะล้างข้อมูลในฐานข้อมูล Firestore ที่เป็นของ projectId ที่กำหนดค่าไว้สำหรับโปรแกรมจำลอง Firestore
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
เมธอดนี้จะรับอินสแตนซ์ Firestore สำหรับบริบทการทดสอบนี้ อินสแตนซ์ Firebase JS Client SDK ที่แสดงผลสามารถใช้กับ Client SDK API (v9 แบบแยกส่วนหรือ v9 แบบเข้ากันได้)
แสดงภาพการประเมินกฎ
โปรแกรมจำลอง Cloud Firestore ช่วยให้คุณแสดงภาพคำขอของไคลเอ็นต์ใน UI ของชุดโปรแกรมจำลอง รวมถึงการติดตามการประเมินสำหรับกฎความปลอดภัยของ Firebase
เปิดแท็บ Firestore > คำขอ เพื่อดูลำดับการประเมินโดยละเอียดสำหรับคำขอแต่ละรายการ
สร้างรายงานการทดสอบ
หลังจากเรียกใช้ชุดการทดสอบแล้ว คุณจะเข้าถึงรายงานความครอบคลุมของการทดสอบที่แสดงวิธีประเมินกฎความปลอดภัยแต่ละข้อได้
หากต้องการรับรายงาน ให้ค้นหาปลายทางที่เปิดเผยในโปรแกรมจำลองขณะที่โปรแกรมจำลองกำลังทำงานอยู่ หากต้องการเวอร์ชันที่เหมาะกับเบราว์เซอร์ ให้ใช้ URL ต่อไปนี้
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
ซึ่งจะแบ่งกฎออกเป็นนิพจน์และนิพจน์ย่อยที่คุณวางเมาส์เหนือเพื่อดูข้อมูลเพิ่มเติมได้ รวมถึงจำนวนการประเมินและค่าที่แสดงผล หากต้องการข้อมูลเวอร์ชัน JSON แบบดิบ ให้ใส่ URL ต่อไปนี้ในการค้นหา
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage
ความแตกต่างระหว่างโปรแกรมจำลองกับเวอร์ชันที่ใช้งานจริง
- คุณไม่จำเป็นต้องสร้างโปรเจ็กต์ Cloud Firestore อย่างชัดแจ้ง โปรแกรมจำลองจะสร้างอินสแตนซ์ที่เข้าถึงโดยอัตโนมัติ
- โปรแกรมจำลอง Cloud Firestore ไม่ทำงานร่วมกับโฟลว์ Firebase Authentication ปกติ
แต่เราได้จัดเตรียมเมธอด
initializeTestApp()ไว้ในไลบรารีrules-unit-testingใน Firebase Test SDK ซึ่งใช้ช่องauthแฮนเดิล Firebase ที่สร้างขึ้นโดยใช้เมธอดนี้จะทำงานราวกับว่าได้ตรวจสอบสิทธิ์เป็นเอนทิตีที่คุณระบุไว้เรียบร้อยแล้ว หากคุณส่งnullแฮนเดิลจะทำงานเหมือนกับผู้ใช้ที่ไม่ได้ตรวจสอบสิทธิ์ (auth != nullกฎจะไม่สำเร็จ เช่น)
แก้ปัญหาที่ทราบ
ขณะใช้โปรแกรมจำลอง Cloud Firestore คุณอาจพบปัญหาที่ทราบต่อไปนี้ โปรดทำตามคำแนะนำด้านล่างเพื่อแก้ปัญหาลักษณะการทำงานที่ผิดปกติที่คุณพบ หมายเหตุเหล่านี้เขียนขึ้นโดยคำนึงถึงไลบรารีการทำ Unit Test สำหรับกฎความปลอดภัย แต่แนวทางทั่วไปสามารถใช้ได้กับ Firebase SDK ทุกรายการ
ลักษณะการทำงานของการทดสอบไม่สอดคล้องกัน
หากการทดสอบผ่านและไม่ผ่านเป็นครั้งคราว แม้ว่าจะไม่มีการเปลี่ยนแปลงการทดสอบเองก็ตาม คุณอาจต้องตรวจสอบว่าการทดสอบมีการจัดลำดับอย่างถูกต้อง
การโต้ตอบส่วนใหญ่กับโปรแกรมจำลองเป็นแบบอะซิงโครนัส ดังนั้นโปรดตรวจสอบอีกครั้งว่าโค้ดอะซิงโครนัสทั้งหมดมีการจัดลำดับอย่างถูกต้อง คุณสามารถแก้ไขการจัดลำดับได้โดยการเชื่อมโยง Promise หรือใช้สัญกรณ์ await อย่างอิสระ
โดยเฉพาะอย่างยิ่ง ให้ตรวจสอบการดำเนินการแบบอะซิงโครนัสต่อไปนี้
- การตั้งค่ากฎความปลอดภัย เช่น
initializeTestEnvironment - การอ่านและการเขียนข้อมูล เช่น
db.collection("users").doc("alice").get() - การยืนยันการดำเนินการ รวมถึง
assertSucceedsและassertFails
การทดสอบจะผ่านเฉพาะครั้งแรกที่คุณโหลดโปรแกรมจำลอง
โปรแกรมจำลองมีสถานะ โดยจะเก็บข้อมูลทั้งหมดที่เขียนลงในหน่วยความจำ ดังนั้นข้อมูลจะสูญหายทุกครั้งที่โปรแกรมจำลองปิดลง หากคุณทำการทดสอบหลายรายการกับรหัสโปรเจ็กต์เดียวกัน การทดสอบแต่ละรายการอาจสร้างข้อมูลที่อาจส่งผลต่อการทดสอบครั้งต่อๆ ไป คุณสามารถใช้เมธอดใดเมธอดหนึ่งต่อไปนี้เพื่อข้ามลักษณะการทำงานนี้
- ใช้รหัสโปรเจ็กต์ที่ไม่ซ้ำกันสำหรับการทดสอบแต่ละรายการ โปรดทราบว่าหากเลือกทำเช่นนี้ คุณจะต้องเรียก
initializeTestEnvironmentเป็นส่วนหนึ่งของการทดสอบแต่ละรายการ เนื่องจากระบบจะโหลดกฎโดยอัตโนมัติสำหรับรหัสโปรเจ็กต์เริ่มต้นเท่านั้น - ปรับโครงสร้างการทดสอบเพื่อไม่ให้โต้ตอบกับข้อมูลที่เขียนไว้ก่อนหน้านี้ (เช่น ใช้คอลเล็กชันอื่นสำหรับการทดสอบแต่ละรายการ)
- ลบข้อมูลทั้งหมดที่เขียนระหว่างการทดสอบ
การตั้งค่าการทดสอบซับซ้อนมาก
เมื่อตั้งค่าการทดสอบ คุณอาจต้องการแก้ไขข้อมูลในลักษณะที่
Cloud Firestore Security Rules ไม่อนุญาต หากกฎทำให้การตั้งค่าการทดสอบซับซ้อน ให้ลองใช้ RulesTestEnvironment.withSecurityRulesDisabled ในขั้นตอนการตั้งค่า เพื่อให้การอ่านและการเขียนไม่ทริกเกอร์ข้อผิดพลาด PERMISSION_DENIED
หลังจากนั้น การทดสอบจะดำเนินการในฐานะผู้ใช้ที่ผ่านการตรวจสอบสิทธิ์หรือไม่ผ่านการตรวจสอบสิทธิ์โดยใช้ RulesTestEnvironment.authenticatedContext และ unauthenticatedContext ตามลำดับ ซึ่งช่วยให้คุณตรวจสอบได้ว่า Cloud Firestore Security Rules อนุญาต / ปฏิเสธ
กรณีต่างๆ ได้อย่างถูกต้อง