How to test with application env in async: true
It is quite common for Elixir application to be configured via application env (which is set in config/
files and accessed with Application.get_env
and such). However, this application env is global and therefore is very difficult to get right when testing with use ExUnit.Case, async: true
.
This article describes how to overcome this problem with Repatch library
Problem
You have a configuration which controls a feature-flag in config/config.exs
import Config
config :my_app, :features,
lucky_feature_enabled: System.get_env("LUCKY_FEATURE") == "1"
Which controls this simple code
defmodule EightBall do
def ask(_question) do
if Application.get_env(:my_app, :features)[:lucky_feature_enabled] do
Enum.random([:absolutely, :sure, :definitely])
else
Enum.random([:no, :no_way, :definitely_not])
end
end
end
And you have these tests
test "Enabled feature" do
Application.put_env(:my_app, :features, lucky_feature_enabled: true)
assert EightBall.ask("Is it awesome?") in [:absolutely, :sure, :definitely]
end
And
test "Disabled feature" do
assert EightBall.ask("Is it awesome?") in [:no, :no_way, :definitely_not]
end
Testing with async: true
won’t be possible, because if the test of enabled feature test is executed before the disabled test, env will be set and the second test will fail. And executing tests with async: false
reduces performance of testing and requires manual cleanup of application env after the test completion.
Solution
Repatch library provides a simple solution to the problem.
-
First, install it with this code in
mix.exs
file:def deps do [ {:repatch, "~> 1.2"} ] end
Then
mix deps.get
-
Setup Repatch with this code in
test/test_helper.exs
file:ExUnit.start() Repatch.setup() Repatch.Application.setup()
-
And just add this into your test file and env will be isolated for each test.
use Repatch.ExUnit, isolate_env: :local
Voila
Now these tests are safe to be used with async: true
testing mode. Repatch is a powerful and small library which makes testing in Elixir very simple. Please check out the docs for all available features: