Issues running tests with a Phoenix 1.3 app that uses GenServer processes

Having an issue running tests for my Phoenix application, not sure how to start investigating or what to do.

Standard Phoenix 1.3 app, Elixir 1.4, Postgres 9.5

Running tests causes this error:

15:15:50.205 [error] GenServer :second_worker terminating
** (DBConnection.OwnershipError) cannot find ownership process for #PID<0.337.0>.

When using ownership, you must manage connections in one
of the four ways:

* By explicitly checking out a connection
* By explicitly allowing a spawned process
* By running the pool in shared mode
* By using :caller option with allowed process

The first two options require every new process to explicitly
check a connection out or be allowed by calling checkout or
allow respectively.

The third option requires a {:shared, pid} mode to be set.
If using shared mode in tests, make sure your tests are not
async.

The fourth option requires [caller: pid] to be used when
checking out a connection from the pool. The caller process
should already be allowed on a connection.

If you are reading this error, it means you have not done one
of the steps above or that the owner process has crashed.

See Ecto.Adapters.SQL.Sandbox docs for more information.
    (db_connection) lib/db_connection.ex:926: DBConnection.checkout/2
    (db_connection) lib/db_connection.ex:742: DBConnection.run/3
    (db_connection) lib/db_connection.ex:584: DBConnection.prepare_execute/4
    (ecto) lib/ecto/adapters/postgres/connection.ex:73: Ecto.Adapters.Postgres.Connection.prepare_execute/5
    (ecto) lib/ecto/adapters/sql.ex:256: Ecto.Adapters.SQL.sql_call/6
    (ecto) lib/ecto/adapters/sql.ex:426: Ecto.Adapters.SQL.execute_and_cache/7
    (ecto) lib/ecto/repo/queryable.ex:133: Ecto.Repo.Queryable.execute/5
    (myproject) lib/myproject/second_worker.ex:68: MyProject.SecondWorker.detect_late_instances/0
    (myproject) lib/myproject/second_worker.ex:27: MyProject.SecondWorker.handle_info/2
    (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:686: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: :second_worker

application.ex looks like:

children = [
	supervisor(MyProject.Repo, []),
	supervisor(MyProject.Endpoint, []),
	worker(MyProject.FirstWorker, []),
	worker(MyProject.SecondWorker, [])
]
opts = [strategy: :one_for_one, name: MyProject.Supervisor]
Supervisor.start_link(children, opts)

FirstWorker and SecondWorker basically do this:

defmodule MyProject.SecondWorker do
  use GenServer

  alias MyProject.Repo


  def start_link(args) do
    GenServer.start_link(__MODULE__, args, name: :second_worker)
  end

  def init(args) do
    schedule_next(1) # send one immediately

    {:ok, args}
  end

  def handle_info(:check_database, %{
  	touch_the_database()

    schedule_next(5000)

    {:noreply, state}
  end

  defp schedule_next(next_time) do
    Process.send_after(self(), :check_database, next_time * 1000)
  end

  defp touch_the_database() do
  	# not exactly this, but there are a bunch of calls to Repo that updates the database
  	Repo.get_by(MyProject.User, id: 1)
  	Repo.delete_all(MyProject.User)
  end
end

Uncommenting the two FirstWorker and SecondWorker lines from application.ex makes tests run normally.

The application itself runs normally outside of tests, and the tests used to work prior to creating the SecondWorker

  1. Are phoenix controller tests run with the full application defined in application.ex running?
  2. How should I go about fixing this so my tests donā€™t die because of FirstWorker and SecondWorker?
  3. How should a phoenix/elixir app be structured with these worker processes that check for updates every hour?
  4. How should the tests be written for testing phoenix controllers, while still being close to the production application, and allowing for testing the two worker processes as well?
  5. Oh god how do I make this work?

You might be interested in learning more about ecto sandbox:

https://hexdocs.pm/ecto/Ecto.Adapters.SQL.Sandbox.html

2 Likes