I created Passby, a mock HTTP server written 100% in Elixir with 0 runtime dependencies.
It is designed as a lightweight drop-in replacement for Bypass, keeping the same API and semantics without pulling in plug_cowboy, cowboy, cowlib, or ranch into your test environment.
Quick Example
test "fetches user profile" do
bypass = Passby.open()
Passby.expect_once(bypass, "GET", "/api/users/42", fn conn ->
Passby.Conn.resp(conn, 200, ~s({"id": 42, "name": "Alice"}))
end)
url = "http://127.0.0.1:#{bypass.port}/api/users/42"
assert {:ok, %{"name" => "Alice"}} = MyClient.get_user(url)
end
I’ve just added this in passby v0.1.1 while keeping 100% backward compatibility with Bypass:
Now %Passby{} includes the `.url` field, and there’s also a helper Passby.url/1,2:
# 1. Using the struct field:
assert {:ok, %{"name" => "Alice"}} = MyClient.get_user("#{bypass.url}/api/users/42")
# 2. Or using the Passby.url/2 helper (handles leading slashes automatically):
assert {:ok, %{"name" => "Alice"}} = MyClient.get_user(Passby.url(bypass, "/api/users/42"))
# 3. Existing Bypass-style code using .port continues to work unchanged:
assert {:ok, %{"name" => "Alice"}} = MyClient.get_user("http://127.0.0.1:#{bypass.port}/api/users/42")
Regarding the zero dependencies, yes, exactly! It relies entirely on standard Erlang/OTP (:gen_tcp, :inet, and :erlang.decode_packet) and provides a lightweight Passby.Conn struct matching Plug.Conn’s API conventions. This allows existing tests to migrate cleanly without bringing Cowboy, Ranch, or Plug into the dependency tree.