Advanced Configuration
View SourceThis guide covers advanced Reqord features for complex testing scenarios.
Configuration Options
Configure Reqord in your config/test.exs:
config :reqord,
# Default recording mode
default_mode: :none,
# Cassette directory
cassette_dir: "test/support/cassettes",
# Request matching strategy
match_on: [:method, :uri],
# Binary storage configuration
max_inline_size: 1_048_576, # 1MB
binary_storage: :auto, # :auto, :inline, :external
object_directory: "test/support/cassettes/objects",
# Stream replay speed
stream_speed: :instant # :instant, :realtimeRequest Matching
Control how Reqord matches requests to cassettes:
Default Matching (Method + URI)
By default, Reqord matches on HTTP method and full URI:
test "default matching" do
# These match the same cassette entry:
Req.get("https://api.example.com/users")
Req.get("https://api.example.com/users") # Replays from cassette
endCustom Matchers
Override matchers globally or per-test:
# Global configuration
config :reqord, match_on: [:method, :path, :body]
# Per-test override
@tag match_on: [:method, :path, :query, :body]
test "strict matching" do
# Matches on method, path, query params, and request body
endAvailable matchers:
:method- HTTP method (GET, POST, etc.):uri- Full URI including query params:path- URL path only:query- Query parameters only:body- Request body:headers- Request headers:host- Hostname:port- Port number
Body Matching
Match on request body for POST/PUT requests:
@tag match_on: [:method, :uri, :body]
test "body matching" do
# Different bodies = different cassette entries
Req.post(url, json: %{name: "Alice"})
Req.post(url, json: %{name: "Bob"})
endCustom Stub Names
Override the default Req.Test stub name:
defmodule MyTest do
use Reqord.Case
@tag req_stub_name: MyApp.CustomStub
test "with custom stub" do
# Uses MyApp.CustomStub instead of default
end
endSpawned Processes
If your test spawns processes that make HTTP requests, allow them explicitly:
test "concurrent requests" do
task = Task.async(fn ->
Req.get("https://api.example.com/data")
end)
# Allow the task's process to use the stub
Reqord.allow(MyApp.ReqStub, self(), task.pid)
{:ok, response} = Task.await(task)
assert response.status == 200
endBinary Data Handling
Reqord automatically handles binary responses (images, PDFs, etc.):
Automatic Storage
test "handles binary data" do
# Large binary responses are automatically stored externally
{:ok, resp} = Req.get("https://example.com/large-file.pdf")
assert byte_size(resp.body) > 1_000_000
endStorage Configuration
config :reqord,
# Size threshold for external storage
max_inline_size: 1_048_576, # 1MB
# Storage strategy
binary_storage: :auto, # :auto (smart), :inline (in cassette), :external (separate files)
# Object storage directory
object_directory: "test/support/cassettes/objects"Streaming Responses
Reqord supports streaming responses (Server-Sent Events, chunked transfer):
test "handles streaming" do
{:ok, resp} = Req.get("https://api.example.com/stream",
into: fn {:data, data}, {req, resp} ->
# Process streamed data
{:cont, {req, update_in(resp.body, &(&1 <> data))}}
end
)
assert resp.body =~ "streamed content"
endConfigure replay speed:
config :reqord,
stream_speed: :instant # Replay instantly (default)
# stream_speed: :realtime # Replay at original speedCassette Organization
For advanced cassette organization strategies, see:
- Cassette Organization Guide - Named builders, custom paths, etc.
- Macro Support Guide - Macro-generated tests
Quick Example: Named Builders
# config/test.exs
config :reqord,
cassette_path_builders: %{
api: fn context -> "api/#{context.test}" end,
llm: fn context ->
provider = get_in(context, [:macro_context, :provider])
"providers/#{provider}/#{context.test}"
end
}
# test file
defmodule APITest do
use Reqord.Case, cassette_path_builder: :api
# Cassettes: api/test_name.jsonl
end
defmodule LLMTest do
use Reqord.Case, cassette_path_builder: :llm
# Cassettes: providers/google/test_name.jsonl
endApplication Configuration
Set default mode in your config files:
# config/test.exs
config :reqord, default_mode: :none
# config/dev.exs (for development testing)
config :reqord, default_mode: :new_episodesCleaning Up Old Cassettes
Reqord provides mix tasks for cassette management:
# Remove unused cassettes
mix reqord.prune
# Rename cassettes after test refactoring
mix reqord.rename old_name new_name
Debugging
Enable detailed logging:
config :logger, level: :debugCheck cassette contents:
# Cassettes are JSON Lines format
cat test/support/cassettes/MyTest/my_test.jsonl | jq
Performance Tips
- Use
:nonemode in CI - Fast, deterministic tests - Group related requests - One test per logical operation
- Use named builders - Cleaner organization for large projects
- Prune regularly - Remove unused cassettes
- External storage - Keep cassettes small for large binary responses
See Also
- Getting Started - Basic usage
- Cassette Organization - Organize cassettes for complex projects
- Macro Support - Handle macro-generated tests
- File Management - Cassette file format and management