Sanjibukai
How to get rid off a warning about module being undefined when module is in a script .exs file? (from [Programming Phoenix 1.4])
Hello everybody,
I’m following along the Programming Phoenix 1.4 Book.
And at a moment we have the following simple code that do an HTTP request using erlang :httpc (excerpt simplified):
defp fetch_data(url) do
{:ok, res} = :httpc.request(url)
res
end
And for testing purpose, we want to mock the HTTP request from :httpc.
But for that we defined in the regular code itself a “conditional” use of the mock instead of the regular library when the code is running in the tests.
So we first defined a config option for the test environment in config.test.exs like so:
# config/test.exs
config :info_sys, :wolfram, http_client: InfoSys.Test.HTTPClient
That it triggers the mock HTTPClient in the module InfoSys.Test.HTTPClient when running in the test environment thanks to the following code in the code (located in a module named Wolfram in the example):
# lib/info_sys/wolfram.ex
@http Application.get_env(:info_sys, :wolfram)[:http_client] || :httpc
defp fetch_data(url) do
{:ok, res} = @http.request(url)
res
end
So we’re using :httpc in all environment but the test environment.
Now the mock HTTP client is in an Elixir Script file located somewhere within the test directory:
# test/backends/http_client.exs
defmodule InfoSys.Test.HTTPClient do
def request(url)
...
data
end
end
In order to this to work we carefully included the code to be required in top of the test_helper.exs file:
# test/test_helper.exs
Code.require_file("backends/http_client.exs", __DIR__)
ExUnit.start()
Now everything work but I always get the following warning:
warning: InfoSys.Test.HTTPClient.request/1 is undefined (module InfoSys.Test.HTTPClient is not available or is yet to be defined)
lib/info_sys/wolfram.ex:4 InfoSys.Wolfram.fetch_data/1
Here I put back the code where the warning is located:
# lib/info_sys/wolfram.ex
@http Application.get_env(:info_sys, :wolfram)[:http_client] || :httpc
defp fetch_data(url) do
{:ok, res} = @http.request(url) # Warning on this line
res
end
This warning really bothers me and I didn’t find a way to get rid of the warning.
I guess that this is related to the lack of .beam file generated for .exs files.
So I even tried to change the mock module inside a .ex file, but it seems that since it’s in the test folder it didn’t get compiled and that I still to use the Code.require_file to make it work.
Has anyone have any idea on how to clean up this warning?
Thank you very much.
Most Liked
benwilson512
NobbZ’s suggestion is a good one. Also however this is an anti-pattern. Do the Application.get_env call at runtime. This will also remove your warning.
benwilson512
I think I was maybe a bit hasty in my reply. It’s an anti-pattern for libraries, but it works just fine for application code. It’s an anti-pattern for libraries because it is only re-evaluated when the library is compiled, which can mean it can get set and not un-set when config changes. For application code which is always recompiled when config changes it’s less of an issue.
In the general case though, configuration has changed a meaningful amount since earlier versions of Elixir, and some old patterns may still be out there that aren’t ideal.
shawarma
Fair enough!
Just for completeness sake, could you elaborate on this and what said config changes mean for this specific issue?
NobbZ
The proper way were to add test/support to :elixirc_path or something and save the module in a proper *.ex file in that folder. Then no Code function is necessary anymore.
You can see an example of how to do that in a phoenix project, they are already generated with that pattern in mind.
axelson
What do you mean when you say “not production-friendly”? If you’re worried about performance fetching data from the application env is just from memory and very fast, likely 10,000 (completely non-scientific estimate) times faster than the network call that you make on the very next line. I would say that it will almost never be a problem.








