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 Patterns

Common patterns for testing Soroban contracts with Testkit: a shared setup(), multi-contract interactions, and deterministic ledger time.

AudienceContract authors
Cratesfixtures · assert
Read time4 minutes

Unit test structure

#![allow(unused)]
fn main() {
#[cfg(test)]
mod tests {
    use super::*;
    use soroban_testkit_fixtures::builder::TestContextBuilder;

    fn setup() -> TestContext {
        TestContextBuilder::new()
            .with_users(3)
            .build()
    }

    #[test]
    fn test_happy_path() {
        let ctx = setup();
        // ...
    }

    #[test]
    #[should_panic(expected = "InsufficientBalance")]
    fn test_insufficient_balance() {
        let ctx = setup();
        // ...
    }
}
}

Cross-contract testing

Register multiple contracts and test interactions:

#![allow(unused)]
fn main() {
#[test]
fn test_contract_interaction() {
    let ctx = TestContextBuilder::new().with_users(2).build();

    let token_id = ctx.env.register(TokenContract, ());
    let vault_id = ctx.env.register(VaultContract, (&token_id,));

    let vault_client = VaultClient::new(&ctx.env, &vault_id);
    vault_client.deposit(&ctx.users[0], &1000);

    // Assert both contracts behaved correctly
}
}

Time-dependent tests

Manipulate ledger state for time-sensitive logic:

#![allow(unused)]
fn main() {
#[test]
fn test_vesting_unlock() {
    let ctx = TestContextBuilder::new().with_users(1).build();

    ctx.env.ledger().set(LedgerInfo {
        timestamp: 1_700_000_000,
        ..Default::default()
    });

    // ... assert locked

    ctx.env.ledger().set(LedgerInfo {
        timestamp: 1_800_000_000,
        ..Default::default()
    });

    // ... assert unlocked
}
}
Reset between cases

Each TestContext owns its own Env, so ledger writes and storage never leak between tests. Share a setup() helper instead of a mutable global fixture.

Where to go next

Budget-aware testing

Pin these patterns down with CPU and memory regression assertions.

Property testing

Replace hand-picked inputs with Soroban-aware generators.

soroban-testkit-assert

The full matcher API for events and authorizations.