Skuld.Effects.Port.Repo.Test (skuld v0.23.0)
View SourceStateless test handler for Port.Repo.Contract.
Provides a function handler via new/1 for use in a Port.with_handler/3
registry. Write operations (insert, update, delete) apply changeset
changes and return {:ok, struct}. All read operations go through an
optional fallback function, or raise a clear error.
This applies the "fail when consistency cannot be proven" approach —
reads never silently return nil or [] because the adapter has no
basis for claiming a record does or doesn't exist.
Usage
alias Skuld.Effects.Port
alias Skuld.Effects.Port.Repo
# Writes only — reads will raise:
comp
|> Port.with_handler(%{Repo.Contract => Repo.Test.new()})
|> Throw.with_handler()
|> Comp.run!()
# With fallback for reads:
comp
|> Port.with_handler(%{
Repo.Contract => Repo.Test.new(
fallback_fn: fn
:get, [User, 1] -> %User{id: 1, name: "Alice"}
:all, [User] -> [%User{id: 1, name: "Alice"}]
end
)
})
|> Throw.with_handler()
|> Comp.run!()Differences from Repo.InMemory
Repo.Test is stateless — writes apply changesets and return {:ok, struct}
but nothing is stored. There is no read-after-write consistency.
Repo.InMemory is stateful — writes store records and PK-based reads can
find them. Use Repo.InMemory when your test needs read-after-write
consistency. Use Repo.Test when you only need fire-and-forget writes.
Summary
Functions
Create a new Test handler function.
Functions
Create a new Test handler function.
Returns a 3-arity function (mod, operation, args) -> result suitable
for use as a resolver in Port.with_handler/3.
Options
:fallback_fn- a 2-arity function(operation, args) -> resultthat handles read operations. If the function raisesFunctionClauseError(no matching clause), dispatch falls through to an error. If omitted, all reads raise immediately.
Examples
# Writes only
Repo.Test.new()
# With fallback for specific reads
Repo.Test.new(
fallback_fn: fn
:get, [User, 1] -> %User{id: 1, name: "Alice"}
:all, [User] -> [%User{id: 1, name: "Alice"}]
:exists?, [User] -> true
end
)