3
votes

What is the correct way of running tests that access multiple databases?

I'm writing a tiny API which has to access multiple databases.

I defined 2 Repos each wrapping a different database:

# config/dev.exs, config/test.exs, ...
config :my_app, MyApp.DbStatusRepo,
  adapter: Ecto.Adapters.Postgres,
  ....

config :my_app, MyApp.DbDefinitionRepo,
  adapter: Ecto.Adapters.Postgres,
  ...

# lib/my_app/db_status_repo.ex
defmodule MyApp.DbStatusRepo do
  use Ecto.Repo, otp_app: :my_app
end

# lib/my_app/db_definition_repo.ex
defmodule MyApp.DbDefinitionRepo do
  use Ecto.Repo, otp_app: :my_app
end

This works when running the server but I can not find a way to run my tests without them expecting the default MyApp.Repo.

I updated (and added) aliases for both repos.

I changed all references to Repo, but I'm pretty sure it's failing before running my test suite.

Running mix test yields the following error:

(Mix) could not load SourcesApi.Repo, error: :nofile. Please pass a proper repo with the -r option.

Passing another repo with -r option does not change anything. Same error.

My Env:

  • Elixir: 1.1.1
  • Phoenix: 1.0.3
  • Ecto: 1.0.6

Thank You for your help.

2

2 Answers

1
votes

First, you need start the repo in lib/my_app.ex

# Start the Ecto repository
worker(MyApp.DbStatusRepo, []),
worker(MyApp.DbDefinitionRepo, []),

Next, prepare repo in test/test_helper.exs

Mix.Task.run "ecto.create", ["--quiet", "-r", "MyApp.DbDefinitionRepo"]
Mix.Task.run "ecto.migrate", ["--quiet", "-r", "MyApp.DbDefinitionRepo"]
Ecto.Adapters.SQL.begin_test_transaction(MyApp.DbDefinitionRepo)
0
votes

The MyApp.Repo is aliased in test/support/conn_case.ex which is why you can call Repo.get(...):

  using do
    quote do
      # Import conveniences for testing with connections
      use Phoenix.ConnTest

      alias MyApp.Repo
      ...
    end
  end

  setup tags do
     unless tags[:async] do
       Ecto.Adapters.SQL.restart_test_transaction(MyApp.Repo, [])
     end

    :ok
  end

You will need to update that alias to one of the repos that you have specified. However if you have two repositories that you are using for different purposes then you should explicitly use MyApp.DbStatusRepo.get(...) and MyApp.DbDefinitionRepo.get(...) when each one is relevant.