| name | elixir-testing |
| description | ExUnit testing patterns, Mox for mocking, StreamData for property-based testing, and Phoenix test cases for Elixir applications. |
Elixir Testing
When to Activate
Use this skill when:
- Writing ExUnit tests for Elixir or Phoenix applications
- Setting up Mox for mock-based testing
- Implementing property-based tests with StreamData
- Writing Phoenix controller or LiveView tests
- Setting up test factories with ExMachina
- Debugging flaky concurrent tests in Elixir
- Setting up code coverage with excoveralls
- Testing GenServer behavior and OTP processes
ExUnit Basics
defmodule MyApp.CalculatorTest do
use ExUnit.Case, async: true # Always async: true unless DB or shared state
describe "add/2" do
test "adds two positive numbers" do
assert Calculator.add(1, 2) == 3
end
test "handles negative numbers" do
assert Calculator.add(-1, 1) == 0
end
end
describe "divide/2" do
test "returns {:error, :division_by_zero} when divisor is 0" do
assert {:error, :division_by_zero} = Calculator.divide(10, 0)
end
end
end
Mox for Compile-Safe Mocks
# 1. Define behaviour
defmodule MyApp.Payments.Gateway do
@callback charge(amount :: integer(), token :: String.t()) ::
{:ok, map()} | {:error, String.t()}
end
# 2. Implementation
defmodule MyApp.Payments.StripeGateway do
@behaviour MyApp.Payments.Gateway
def charge(amount, token) do
Stripe.Charge.create(%{amount: amount, source: token, currency: "usd"})
end
end
# 3. Register mock in test/test_helper.exs
Mox.defmock(MyApp.MockGateway, for: MyApp.Payments.Gateway)
# 4. Configure application to use mock in test env
# config/test.exs
config :my_app, :payment_gateway, MyApp.MockGateway
# 5. Use in tests
defmodule MyApp.OrderServiceTest do
use ExUnit.Case, async: true
import Mox
setup :verify_on_exit!
test "processes payment on order creation" do
expect(MyApp.MockGateway, :charge, fn 1000, "tok_test" -> {:ok, %{id: "ch_123"}} end)
assert {:ok, order} = OrderService.create(%{amount: 1000, token: "tok_test"})
assert order.payment_id == "ch_123"
end
end