Mox

Mock library for Elixir that enforces behaviour-based contracts — creates test mocks that validate against Elixir @behaviour callbacks. Mox features: Mox.defmock/2 creates mock modules, expect/4 sets expectations with call count, stub/3 allows any number of calls, verify_on_exit!/1 asserts all expectations satisfied, allow/3 for async test access, global mode for non-concurrent tests, and strict adherence to @behaviour interface. Created by José Valim (Elixir creator) with explicit-contract philosophy — mocks must match a defined behaviour.

Evaluated Mar 06, 2026 (0d ago) v1.x
Homepage ↗ Repo ↗ Developer Tools elixir mox mocking testing behaviour dependency-injection concurrent
⚙ Agent Friendliness
69
/ 100
Can an agent use this?
🔒 Security
94
/ 100
Is it safe for agents?
⚡ Reliability
89
/ 100
Does it work consistently?

Score Breakdown

⚙ Agent Friendliness

MCP Quality
--
Documentation
88
Error Messages
88
Auth Simplicity
98
Rate Limits
98

🔒 Security

TLS Enforcement
95
Auth Strength
95
Scope Granularity
92
Dep. Hygiene
90
Secret Handling
95

Test-only library — no security surface. Mock implementations in tests should never use real credentials. Mox behaviour contracts improve production code security by enforcing explicit interface contracts.

⚡ Reliability

Uptime/SLA
88
Version Stability
90
Breaking Changes
88
Error Recovery
90
AF Security Reliability

Best When

Your Elixir agent app uses dependency injection via @behaviour modules (recommended pattern) and you want strict contract-enforcing mocks for external services like HTTP clients, LLM APIs, and databases.

Avoid When

You're mocking modules without defined behaviours, need HTTP recording/replay, or your codebase doesn't use dependency injection patterns.

Use Cases

  • Agent external API mocking — defmodule HTTPClientMock, do: use(Mox); Mox.defmock(HTTPClientMock, for: MyApp.HTTPClient); expect(HTTPClientMock, :get, fn url -> {:ok, %{body: 'result'}} end); agent code under test calls behaviour, gets mock response
  • Agent behaviour contract testing — defbehaviour MyApp.LLMClient, do: @callback complete(String.t()) :: {:ok, String.t()} | {:error, term}; Mox ensures mock matches spec; agent LLM client mock can't accidentally implement wrong interface
  • Concurrent agent tests — Mox.allow(MockHTTP, self(), task_pid) allows background agent Task to use test process mock; async: true tests with Mox.allow share mocks safely; agent concurrent tests don't interfere via mock ownership
  • Stub for setup-heavy agent mocks — stub(MockLLM, :embed, fn _ -> {:ok, [0.1, 0.2, 0.3]} end) allows any number of embedding calls without strict count expectations; agent integration tests needing embedding without caring about call count use stub not expect
  • Agent test isolation — Mox.verify_on_exit!(context) in ExUnit setup; agent test that expects 2 LLM calls but makes 3 fails with clear error; prevents agent tests from silently over-calling external services

Not For

  • Mocking modules without behaviours — Mox requires @behaviour definition; for mocking arbitrary modules without behaviours use Patch or Mock libraries
  • Record-replay HTTP mocking — Mox doesn't record/replay HTTP; for cassette-style mocking use Bypass for Elixir or ExVCR
  • Mocking internal private functions — Mox works on public behaviour callbacks; for mocking private functions refactor to inject dependencies via behaviour

Interface

REST API
No
GraphQL
No
gRPC
No
MCP Server
No
SDK
Yes
Webhooks
No

Authentication

Methods: none
OAuth: No Scopes: No

No auth — test library running in Elixir test environment.

Pricing

Model: open_source
Free tier: Yes
Requires CC: No

Mox is Apache 2.0 licensed, created by Dashbit (José Valim). Free for all use.

Agent Metadata

Pagination
none
Idempotent
Full
Retry Guidance
Not documented

Known Gotchas

  • @behaviour module must be defined before Mox.defmock — Mox.defmock(MyMock, for: MyApp.Behaviour) requires MyApp.Behaviour to exist; defining mock before behaviour causes ArgumentError; agent test setup ordering matters — define behaviours in lib/, mocks in test/support/mocks.ex
  • Mox.allow required for async Task processes — spawned agent Tasks run in separate processes without automatic mock access; Mox.allow(MockHTTP, self(), Task.async(fn -> agent.fetch() end).pid) grants Task access; forgetting allow causes 'no expectation set for process' error in concurrent agent workflows
  • Global mode unsafe for concurrent tests — Mox.set_mox_global() shares mocks across all test processes; async: true tests with global mocks interfere; use global mode only for tests with async: false; agent test suites with mixed async/sync tests must explicitly manage mode
  • expect count is exact not minimum — expect(MockLLM, :complete, 3, fn _ -> {:ok, 'response'} end) fails if complete called 2 or 4 times; agent tests that call LLM variable number of times should use stub not expect; stub allows any call count
  • Mox not Elixir structs — Mox.defmock creates a module not a struct; MyMock is a module name; agent code must be written to accept the mock module as an argument (dependency injection): def fetch(client \\ HTTPClient) — not hardcoded module names
  • stub/3 doesn't verify calls — stub(MockLLM, :embed, fn _ -> {:ok, []} end) sets no expectations; verify_on_exit! doesn't check stubs; agent tests using only stubs never fail even if the mocked function is never called; use expect for agent interactions you want to assert happened

Alternatives

Full Evaluation Report

Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for Mox.

$99

Scores are editorial opinions as of 2026-03-06.

5215
Packages Evaluated
26151
Need Evaluation
173
Need Re-evaluation
Community Powered