Ecto 2.0 SQL Sandbox Error on tests

If anyone else encounters this, I got an answer back on this directly from the language author Jose Valim:

Yes, your understanding of the issue is correct. It is happening because the test process, the one who owns the connection, has exited but the Task is still using its connection. Using {:shared, self()} does not fix it because the test is still owning the connection, you are just sharing it implicitly.

The way to fix is to guarantee the Task has finished before the test exits. This can be done by calling Process.exit(task_pid, :kill). If you don't know the Task PID, you can call Task.Supervisor.which_children(NameOfYourTaskSupervisor) to return all PIDs which you then traverse and kill them. However, if you do this approach, the test cannot run concurrently (as you may kill tasks started by another test).


I had the same problem today and I think I've found a possible solution with allows the tests to run concurrently.

I'm using the technique described here: http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/ to replace Task.Supervisor while running tests.

Instead of:

Task.Supervisor.async_nolink(TaskSupervisor, fn -> (...) end)

I'm doing:

@task_supervisor Application.get_env(:app, :task_supervisor) || Task.Supervisor
# ...
@task_supervisor.async_nolink(TaskSupervisor, fn -> (...) end)

and then I define TestTaskSupervisor

defmodule TestTaskSupervisor do
  def async_nolink(_, fun), do: fun.()
end

and add config :app, :task_supervisor, TestTaskSupervisor in config/test.exs.

This way, I'm sure that the task will run synchronously and finish before the test process.