r11na
How to stop Supervisors starting GenServer during Exunit tests?
I’m having difficult figuring out how to stop supervisors running genservers during my tests and I haven’t found any helpful guides online.
I have the following setup in a test file:
setup do
{:ok, server_pid} = Program.Myserver.start_link()
{:ok, server: server_pid}
end
When I run my tests I get an
** (MatchError) no match of right hand side value: {:error, {:already_started, #PID<0.405.0>}}
No doubt because the supervisor has already started the genserver but I don’t know how to stop it doing this during my tests…
Any ideas on the best way to stop this?
Most Liked
michalmuskala
Since Elixir 1.5 the recommened approach for starting processes in a test is to use start_supervised/2. This is an easy way to ensure the process is started and stopped together with the test process.
blatyo
What I typically do for this situation is set something like this in config/test.exs:
config :my_app, :env, :test
Then in my application supervisor, I separate out the processes I don’t want to start automatically and check the env.
children = [{MyApp.Endpoint, []), {MyApp.Repo, []}]
children = case Application.get_env(:my_app, :env) do
:test -> children ++ [{MyApp.OtherThing, []}]
_ -> children
end
Supervisor.init(children, strategy: :one_for_one)
If there’s a better way than this, I’m not aware of it.
SZJX
It seems that the easiest way to solve it is just to start your GenServer under a different name, using the :name option? Though if your GenServer functions depend on a hardcoded :name such as __MODULE__ it would indeed making testing harder.
e.g. instead of writing
def start_link(_) do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
write
def start_link(opts) do
GenServer.start_link(__MODULE__, :ok, opts)
end
and then the child spec:
%{
id: MyApp.MyGenServer,
start: {MyApp.MyGenserver, :start_link, [[name: MyApp.MyGenServer]]}
}
then in your test you can give a different name, e.g.
setup context do
_ = start_supervised!({MyApp.MyGenserver, name: context.test})
%{producer: context.test}
end
OvermindDL1
You just need to tear it down after, see another thread already talking about this at:
![]()
blatyo
The setup callback needs you to return one of those types. Like:
setup do
start_supervised(CeresCore.Queue.Consumers.PaymentConsumer)
:ok
end
The other issue appears to be that CeresCore.Queue.Consumers.PaymentConsumer.start_link/1 is not a function that exists.







