5

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 Answers2

3

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)
Kabie
  • 10,489
  • 1
  • 38
  • 45
  • Thank You very much. I completely missed what the test helper was actually doing. I added create & migrate actions for both repos. Thank You again. – Jacek Pakulski Nov 12 '15 at 11:18
  • 1
    Just in case anyone else stumbles across this answer, `Mix.Task.run` will abort and return `:noop` if the same command is run more than once, regardless of arguments. If you want to do something like this, you'd need to run `Mix.Task.reenable(task)` for both tasks before running them for the second repo. – Matt McClure Feb 03 '16 at 01:30
0

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.

Gazler
  • 83,029
  • 18
  • 279
  • 245
  • Thank You for the reply. I was not too clear in my question that I already updated / added aliases. My problem was completely caused by the create and migrate tasks defined in the test_helper.exs as described by Kabie. – Jacek Pakulski Nov 12 '15 at 11:23