Guides

No-DB unit tests

Use Biome without a store, for pure unit tests.

Omit the store

If the behavior is a pure function over entities, a database adds setup without helping the assertion. You can use the same blueprints without a store. Biome defaults to NullStore, and entities exist as soon as each Add returns, so there is no need to call BuildAsync unless you want save hooks to run.

TestBiome
    .Start(out _) // NullStore; no BuildAsync needed
    .AddCodeRepository(out var repo)
    .AddPullRequests(out var prs, PullRequests.Draft, PullRequests.Merged);

// act: var summary = PullRequestSummary.From(repo, prs);
Call BuildAsync only when you need a save or the save hooks. For a pure function over entities, building is enough.

When you still want a store

A RecordingStore is a handy test double: it captures the rows Biome would save, so you can assert on order and exclusions without a database. The library's own tests use it:

RecordingStore.cs
internal sealed class RecordingStore : IBiomeStore
{
    internal List<object> Entities { get; } = [];

    public ValueTask SaveAsync(
        IReadOnlyList<object> entities,
        CancellationToken cancellationToken
    )
    {
        Entities.AddRange(entities);
        return ValueTask.CompletedTask;
    }
}
CodeReviewTests.cs
var store = new RecordingStore();
var biome = TestBiome.Start(out var seed, store);

await biome.AddLockedReview(out var activeLock).BuildAsync();

// seed rows precede the four created rows
// store.Entities[0] == seed.Owner; store.Entities[1] == seed.Organization;
// store.Entities.Count == 6

Inspecting what was built

Keep the starting builder when you want entities a helper created, without naming each:

Inspect
var biome = TestBiome.Start(out _);
await biome.AddLockedReview(out var activeLock).BuildAsync();

var review = biome.Last<CodeReviewRecord>(); // created by the helper
// creation order; includes transients; excludes seed rows
var repos = biome.All<CodeRepository>();
All<T>() and Last<T>() include transient entities and aggregate wrappers, but not seed rows. Prefer naming entities with out when the test is about them, and use All / Last for entities that helpers create.