Testing & Mocking
Weld has in-language unit tests: test blocks that live next to your code, run by weld test, and compile away in the server binary. Inside a test you can mock any resource call so the code under test never touches a real database, upstream, or gRPC service.
test blocks
A top-level test "name" { … } block contains ordinary statements plus assert <cond>, which fails the test when its condition is false:
fn clamp(x: int, lo: int, hi: int) -> int {
if x < lo { return lo }
if x > hi { return hi }
return x
}
test "clamp bounds a value" {
assert clamp(5, 0, 10) == 5
assert clamp(-3, 0, 10) == 0
assert clamp(99, 0, 10) == 10
}Tests can call any fn (including ones that make resource calls — see below) and use the full language: let, if, match, and so on. They are stripped from a normal build, so they add nothing to your server.
Running tests
weld test app.weld # compile the test blocks and run them, with a pass/fail summary
weld app.weld --emit test # the same thing (CI-ready: exits non-zero on failure)weld test prints a per-test result line and a summary; a failing assert (or an unmocked resource call) reports which test failed. See examples/tested.weld for a runnable set.
Mocking resource calls
Inside a test, mock installs a fake for a resource call — an upstream call, a database query, or a gRPC rpc — so the code under test never touches a real dependency:
fn checkout(uid: int, amount: int) -> Receipt {
let u = db.getUser(uid) else e { return Receipt { ok: false, note: "no user" } }
let c = billing.charge(uid, amount) else e { return Receipt { ok: false, note: "billing down" } }
return Receipt { ok: c.ok, note: c.id }
}
test "a good checkout charges and confirms" {
mock db.getUser(id) -> User { id: id, name: "Alice", credit: 1000 } # short form: a value
mock billing.charge(user_id, amount) -> Charge { id: "ch_1", ok: true }
let r = checkout(1, 250)
assert r.ok
}
test "a decline is handled" {
mock db.getUser(id) -> User { id: id, name: "Bob", credit: 1000 }
mock billing.charge(uid, amt) { # body form: branch, compute, or `fail`
if amt > 1000 { return Charge { id: "", ok: false } }
return Charge { id: "ch_ok", ok: true }
}
let r = checkout(1, 5000)
assert !r.ok
}mock <resource>.<call>(names) -> <expr>returns a value;mock <resource>.<call>(names) { … }is a full body that may branch, compute from the parameters, orfail. The parameters bind positionally to the call's declared parameters; the return type is the call's declared type.- Default-strict: a resource call reached during a test with no mock installed fails the test immediately (
unmocked call to db.getUser …), so a test can't silently hit the network. - Mocks are scoped to one test — each starts with a clean slate.
- The whole mechanism is compiled away from a normal build (it exists only under
weld test), so it adds nothing to your server binary. - A
fnthat makes resource calls is testable directly (ascheckoutabove) — you don't need to route through an HTTP handler to exercise it.
Not yet mockable: streaming queries, client-/server-/bidi-streaming rpcs, and transaction blocks. See examples/mocked.weld.