Gigitsu

Gigitsu

Why do I need to manually checkout the connection when using a dynamic repo in tests?

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.

Marked As Solved

LostKobrakai

LostKobrakai

Looking at the implemenation of start_owner! it might simply not support dynamic repos. You might need to resort to the older checkout api.

start_owner! lets an external process hold the reference to the connection and that external process has no idea about your dynamic repo. start_owner! on the other hand will keep the sandbox around after the test’s process stops with the end of the testcase and therefore needs to be a separate process to the test process.

Where Next?

Popular in Questions Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New

We're in Beta

About us Mission Statement