Testing GenServer which handle ecto queries

I have a PositionGenServer which uses ecto repository. So when I run tests I receive following errors: ** (DBConnection.OwnershipError) cannot find ownership process for #PID<0.284.0>

For now I’ve ended up with following solution:

defmodule MyApp do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(MyApp.Repo, []),
      worker(MyApp.MyEctofiedGenServer, [[]])
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

defmodule MyApp.Case do
  use ExUnit.CaseTemplate
  use MyApp.Aliases

  setup(opts) do
    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo)

    case Supervisor.restart_child(MyApp.Supervisor, MyEctofiedGenServer) do
      {:ok, _} -> :ok
      {:error, :running} -> :ok
    end

    case Ecto.Adapters.SQL.Sandbox.allow(Repo, self, Process.whereis(MyEctofiedGenServer)) do
      :ok -> :ok
      {:already, :allowed} -> :ok
    end

    on_exit fn ->
      :ok = Supervisor.terminate_child(VOK.Supervisor, MyEctofiedGenServer)
    end

    :ok
  end
end

But it should not work with async: true, because MyEctofiedGenServer can be killed, when parallel test starts, and loose it state.

Does anyone have a better solution?

1 Like

I don’t think it’s possible to run concurrent tests against a supervised GenServer like that. As you say, its state will be destroyed while other tests are relying on it.

One option would be to implement all the functionality of the GenServer as a stateless module, where each individual function can be tested concurrently. Then make a thin stateful layer over the functional abstraction which you can run a smaller integration test on.

2 Likes