0
0
FirebaseHow-ToBeginner · 4 min read

How to Test Security Rules in Firebase: Step-by-Step Guide

To test Firebase security rules, use the Firebase Emulator Suite which simulates your database and storage locally. Write test scripts with the @firebase/rules-unit-testing library to check if your rules allow or deny access as expected before deploying.
📐

Syntax

Testing Firebase security rules involves these key parts:

  • initializeTestEnvironment(): Sets up a local test environment for your rules.
  • loadRules(): Loads your security rules into the test environment.
  • authenticatedContext() or unauthenticatedContext(): Creates a simulated user context.
  • assertSucceeds() and assertFails(): Check if an operation is allowed or denied by your rules.
javascript
import { initializeTestEnvironment, assertSucceeds, assertFails } from '@firebase/rules-unit-testing';
import fs from 'fs';

const testEnv = await initializeTestEnvironment({
  projectId: 'your-project-id',
  firestore: { rules: fs.readFileSync('firestore.rules', 'utf8') }
});

const alice = testEnv.authenticatedContext('alice');

await assertSucceeds(alice.firestore().collection('messages').add({ text: 'Hello' }));
await assertFails(alice.firestore().collection('private').get());
💻

Example

This example shows how to test Firestore rules that allow only authenticated users to add messages and deny reading a private collection.

javascript
import { initializeTestEnvironment, assertSucceeds, assertFails } from '@firebase/rules-unit-testing';
import fs from 'fs';

async function runTests() {
  const testEnv = await initializeTestEnvironment({
    projectId: 'demo-project',
    firestore: { rules: fs.readFileSync('firestore.rules', 'utf8') }
  });

  const alice = testEnv.authenticatedContext('alice');
  const bob = testEnv.unauthenticatedContext();

  // Alice can add a message
  await assertSucceeds(alice.firestore().collection('messages').add({ text: 'Hi!' }));

  // Bob (unauthenticated) cannot add a message
  await assertFails(bob.firestore().collection('messages').add({ text: 'Hi!' }));

  // Alice cannot read private collection
  await assertFails(alice.firestore().collection('private').get());

  await testEnv.cleanup();
}

runTests();
Output
All assertions pass without errors.
⚠️

Common Pitfalls

  • Not loading the latest rules file before testing can cause outdated tests.
  • Forgetting to clean up the test environment leads to resource leaks.
  • Testing only success cases and ignoring failure cases misses security gaps.
  • Using real Firebase instances instead of the emulator risks data corruption.
javascript
/* Wrong: Using real Firebase app for testing (do not do this) */
import { getFirestore } from 'firebase/firestore';
const db = getFirestore(); // connects to live database

/* Right: Use emulator and rules-unit-testing library */
import { initializeTestEnvironment } from '@firebase/rules-unit-testing';

async function setup() {
  const testEnv = await initializeTestEnvironment({ projectId: 'demo' });
  return testEnv;
}
📊

Quick Reference

Tips for testing Firebase security rules:

  • Always use @firebase/rules-unit-testing with the Emulator Suite.
  • Test both allowed and denied operations.
  • Use descriptive user contexts to simulate different roles.
  • Run tests automatically in CI before deploying rules.

Key Takeaways

Use Firebase Emulator Suite and @firebase/rules-unit-testing to test security rules locally.
Write tests that check both allowed and denied access scenarios.
Always load the latest rules file and clean up test environments after tests.
Avoid testing on live Firebase projects to prevent data risks.
Automate security rule tests in your deployment pipeline for safety.