Sanjibukai

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

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

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

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

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

shawarma

Fair enough!

Just for completeness sake, could you elaborate on this and what said config changes mean for this specific issue?

NobbZ

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

axelson

Scenic Core Team

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.

Where Next?

Popular in Questions Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
sabri
Can someone explain the settings of pool_size of Ecto in config file? and what is the recommend size? Thanks
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

We're in Beta

About us Mission Statement