Mocking libraries must not be used — define a behaviour and inject the implementation instead.
Mocks couple tests to call sequences instead of contracts, and their global or process-wide stubbing breaks down under async tests. A behaviour with a test implementation keeps the contract explicit and the test data local.
# BAD — Mox mock wired to the behaviour
Mox.defmock(MyApp.ClientMock, for: MyApp.Client)
expect(MyApp.ClientMock, :fetch, fn id -> {:ok, %{id: id}} end)
# GOOD — behaviour + injected test implementation
defmodule MyApp.TestClient do
@behaviour MyApp.Client
@impl MyApp.Client
def fetch(id), do: {:ok, %{id: id}}
end
MyApp.Worker.fetch(1, client: MyApp.TestClient)Banned modules are matched on their exact segments — MyApp.MockingBird and
MyApp.Mock are project modules, not mocking libraries, and are never flagged.