How to test supervised, named, Agents?

Skip to first unread message

Doug Goldie

Sep 2, 2014, 8:00:40 PM9/2/14
What is the best practice to run isolated tests with a supervised, named Agent?

I have an Agent with 4 tests.
The tests worked fine starting the Agent in a setup block (like elixirsips #78)

{:ok, agent} = ConsumerAgent.start_link

But after putting it in a supervisor tree and globally naming it, I get errors like this.

** (MatchError) no match of right hand side value: {:error, {:already_started, #PID<0.167.0>}}

So, I guess ExUnit is creating my global Agent by running the application supervision tree.

Removing the setup block gets rid of the error.
But now some tests break -- usually the last one -- because state is being carried over from test to test by the Agent.

For this particular agent, I could merge the tests into one... not a great practice.
I suppose I could write a reset function that initializes the Agent dict....

but what's the right way here to run isolated tests?



Saša Jurić

Sep 3, 2014, 2:07:23 AM9/3/14
One option is to run 
mix test --no-start 
which will prevent the application from being started.

José Valim

Sep 3, 2014, 7:13:13 AM9/3/14
I would typically allow the name to be given as argument. In ConsumerAgent:

    @name __MODULE__

    def start_link(opts \\ []) do
      opts = Keyword.put_new(opts, :name, @name)

    def call_the_agent(name \\ @name) do
      Agent.get(@name, ...)

Then you can use the direct API in your code but pass the agent explicitly during tests.

José Valim
Skype: jv.ptec
Founder and Lead Developer

You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
For more options, visit

Doug Goldie

Sep 4, 2014, 3:39:24 PM9/4/14
Thanks Sasa, Jose,

Both solutions work! 
More importantly, both pushed me to learn more Elixir!
Here's a few comments / questions....

1) Using mix test --no-start
Cool, I didn't realize that was there.

When I tried this, I got an error for the Logger application not running.
Fixed that with Application.start(:logger).
It seemed to make sense to move it to the test_helper.exs, which works.
But it doesn't look like you can move the start option to the test helper because its used earlier in the app.start.

It feels like it might be inflexible as your app mature because
I think you'd be committed to using --no-start all the time.

Would it make sense to have something for default Mix cli options? like a '.mix' file.
I'm not sure it's needed...just thinking out loud :-)

Again this works great. 

2) Passing agent name in args.
I was happy how close my Agent was to Jose's example :-)
I went with this approach. It does make the tests a little more wordy, but not bad.
I noticed I didn't have to use on_exit.

So, the Agent is stopped when the test process dies?

thanks again !

{:ok, agent} = ConsumerAgent.start_link name: {:global, __MODULE__ }
    {:ok, agent: agent}

"get current consumer key", context do
assert ConsumerAgent.get(context[:agent]) == 0

José Valim

Sep 4, 2014, 3:42:31 PM9/4/14
So, the Agent is stopped when the test process dies?

Yes! The test process exits with reason :shutdown, which causes all linked processes to quietly shutdown too!
Reply all
Reply to author
0 new messages