run_test — The Test Harness

run_test is the test equivalent of run_blocking. Use it in every #[test] that runs an effect.

Basic Usage

#![allow(unused)]
fn main() {
use id_effect::{run_test, succeed};

#[test]
fn simple_effect_succeeds() {
    let result = run_test(succeed(42));
    assert_eq!(result, Exit::Success(42));
}
}

run_test returns an Exit<A, E> rather than a Result<A, E>. This lets you assert on the exact exit reason — success, typed failure, defect, or cancellation.

Why Not run_blocking in Tests?

run_blocking is correct but missing test-specific guarantees:

Featurerun_blockingrun_test
Runs the effect
Detects fiber leaks
Deterministic scheduling
Reports leaked resources

Fiber leaks — effects that spawn children and don't join them — are silent in production but become test failures under run_test. This catches a class of resource leak bugs at unit-test time.

Asserting on Exit

#![allow(unused)]
fn main() {
#[test]
fn division_by_zero_fails() {
    let eff = divide(10, 0);
    let exit = run_test(eff);

    // Assert specific failure
    assert!(matches!(exit, Exit::Failure(Cause::Fail(DivError::DivisionByZero))));
}

#[test]
fn effect_that_panics_is_a_defect() {
    let eff = effect!(|_r: &mut ()| {
        panic!("oops");
    });
    let exit = run_test(eff);

    assert!(matches!(exit, Exit::Failure(Cause::Die(_))));
}
}

Exit::Success(a) — the effect succeeded with value a Exit::Failure(Cause::Fail(e)) — the effect failed with typed error e Exit::Failure(Cause::Die(s)) — the effect panicked or encountered a defect Exit::Failure(Cause::Interrupt) — the effect was cancelled

run_test with an Environment

When your effect needs services, provide a test environment:

#![allow(unused)]
fn main() {
#[test]
fn create_user_inserts_into_db() {
    let fake_db = FakeDatabase::new();
    let env = ctx!(DbKey => Arc::new(fake_db.clone()));

    let eff = create_user(NewUser { name: "Alice".into(), age: 30 });
    let exit = run_test_with_env(eff, env);

    assert!(matches!(exit, Exit::Success(_)));
    assert_eq!(fake_db.users().len(), 1);
}
}

run_test_with_env(effect, env) is the full version. run_test(effect) is shorthand for run_test_with_env(effect, ()) when the effect requires no environment.

run_test_and_unwrap

When you're confident an effect succeeds and just want the value:

#![allow(unused)]
fn main() {
#[test]
fn addition_works() {
    let result: i32 = run_test_and_unwrap(succeed(1 + 1));
    assert_eq!(result, 2);
}
}

run_test_and_unwrap panics on any non-success Exit, with a descriptive message. Use it for happy-path tests where a failure is a bug in the test setup.

Fiber Leak Detection

#![allow(unused)]
fn main() {
#[test]
fn this_test_will_fail_due_to_leak() {
    let eff = effect!(|_r: &mut ()| {
        // Spawns a fiber but never joins it
        run_fork(/* … */);
        ()
    });

    // run_test detects the leaked fiber and fails the test
    let exit = run_test(eff);
    // exit: Exit::Failure(Cause::Die("fiber leak detected: 1 fiber(s) not joined"))
}
}

Fix leaks by joining fibers or explicitly cancelling them before the effect completes.