Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Testing your own code

The Fluent API is built on FirestoreDb directly, so there is no built-in way to substitute a fake database into db.fluent(). There are two approaches that work well.

Abstract at your own boundary

Define a trait for what your code needs and implement it over a type holding a FirestoreDb. Your business logic then depends on your trait, and tests provide their own implementation. This keeps Firestore concerns in one place and needs nothing special from this library:

use firestore::*;
use firestore::errors::FirestoreError;
#[derive(Debug, serde::Deserialize)]
struct User;
#[derive(Debug)]
struct MyError;
impl From<FirestoreError> for MyError {
    fn from(_: FirestoreError) -> Self {
        MyError
    }
}
#[async_trait::async_trait]
trait UserRepository {
    async fn find_user(&self, id: &str) -> Result<Option<User>, MyError>;
}

struct FirestoreUserRepository {
    db: FirestoreDb,
}

#[async_trait::async_trait]
impl UserRepository for FirestoreUserRepository {
    async fn find_user(&self, id: &str) -> Result<Option<User>, MyError> {
        Ok(self
            .db
            .fluent()
            .select()
            .by_id_in("users")
            .obj()
            .one(id)
            .await?)
    }
}

// In tests, implement `UserRepository` with an in-memory HashMap.

Run against the Firestore emulator

For tests that should exercise real query, listener and transaction behaviour, point the library at the Firestore emulator:

export FIRESTORE_EMULATOR_HOST="localhost:8080"

No credentials are needed in that mode. This is how the caching and transaction behaviour of this library itself is verified, and it catches things a hand-written fake cannot.

Code that runs pipelines or SQL needs an emulator started in the Enterprise edition, see Firestore emulator.

The low level *Support traits are not public, and the builders’ constructors are crate private, so code cannot be generic over them. The migration guide lists the fluent replacement of every removed method.