Hi everyone,
I’m running into an issue when using a dynamic repository in my tests, and I’m trying to understand why the sandbox behaves differently compared to when I stick with a single statically configured repo.
Here’s a simplified example of my test module:
defmodule Hello.MyTest do
use Hello.DataCase, async: true
setup do
Hello.Repo.start_link(
name: :replica_db,
database: "my_replica_test#{System.get_env("MIX_TEST_PARTITION")}"
)
Hello.Repo.put_dynamic_repo(:replica_db)
Hello.Factory.create_users(10)
:ok
end
test "should test something" do
...
end
end
And my DataCase looks like this:
defmodule Hello.DataCase do
use ExUnit.CaseTemplate
using do
quote do
alias Hello.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query
import Hello.DataCase
end
end
setup tags do
Hello.DataCase.setup_sandbox(tags)
:ok
end
def setup_sandbox(tags) do
pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Hello.Repo, shared: not tags[:async])
on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end)
end
def errors_on(changeset), do: ...
end
My test_helper.exs is also pretty standard:
ExUnit.start()
Ecto.Adapters.SQL.Sandbox.mode(Hello.Repo, :manual)
When I run this with a single, static repo, I don’t have to do anything extra — the sandbox is automatically set up and all my changes are rolled back at the end of the test.
But when I switch to using a dynamic repo (via put_dynamic_repo/1), I suddenly need to explicitly do:
Ecto.Adapters.SQL.Sandbox.mode(Hello.Repo, :manual)
Ecto.Adapters.SQL.Sandbox.checkout(Hello.Repo)
Otherwise, every change I made to the db is committed (eg. the users created by my factory are still there at the end of the test).
My question is:
Why does using a dynamic repo make the sandbox behave differently?
Is there a way to configure the dynamic repo so that I don’t need to manually set the mode and checkout?
Thanks in advance!
edit:
I read this documentation page, but it didn’t help me solve my issue.
Also, it seems like I could define more than one repo in my application’s supervision tree like this:
defmodule Hello.Application do
use Application
@impl true
def start(_type, _args) do
children = [
# Start the Ecto repository
Hello.Repo,
{Hello.Repo, name: :replica_db}
]
Supervisor.start_link(children, [strategy: :one_for_one, name: Hello.Supervisor])
end
end
However, this raises the following error:
** (Mix) Could not start application hello: Hello.Application.start(:normal, []) returned an error: bad child specification, more than one child specification has the id: Hello.Repo.






















