I have been trying like mad to use config based mocks on Elixir. I have defined my mocked module and placed it inside a ".ex" file under the "test/" directory. Then whenever I run "mix test" it fails to load the module. However if I move the mock under "lib/" then everything works just fine. So I was wondering if there is something I'm missing on my configuration and file structure OR if there is a way to tell "mix" to look for source files in another directory in addition to "lib/".
File structure:
my_app/
|
+ -- lib/
| my_lib.ex
| my_service.ex
|
+ ---test/
| test_helper.ex
| my_service_mock.ex
| my_lib_test.exs
|
+----config/
config.exs
test.exs
prod.exs
dev.exs
config/dev.exs
import Config
config :my_app, my_service: MyApp.MyService
config/test.exs
import Config
config :my_app, my_service: MyApp.MyServiceMock
my_lib.ex
defmodule MyLib do
@my_service Application.get_env(:my_app, :my_service)
def do_something, do: @my_service.do_something_else
end
my_service.ex
defmodule MyApp.MyService do
def do_something_else, do: { :ok, "Running business task" }
end
my_service_mock.ex
defmodule MyApp.MyServiceMock do
def do_something_else, do: { :ok, "Faking business task" }
end
my_lib_test.ex
defmodule MyApp.MyLibTest do
use ExUnit.Case
alias MyApp.MyLib
test "MyList.do_something/0 should do it's thing" do
assert { :ok, "Faking business task" } = MyLib.do_something
end
end
The command "mix test" fails with the following error:
== Compilation error in file lib/my_lib.ex ==
** (UndefinedFunctionError) function MyApp.MyServiceMock.do_something_else/0 is undefined (module MyApp.MyServiceMock is not available)
MyApp.MyServiceMock.do_something_else()
lib/my_lib.ex:3: (module)
(stdlib 3.14) erl_eval.erl:680: :erl_eval.do_apply/6
I'm running elixir 1.11.2.
Well, I finally found out the solution on this post on Elixir Forum: https://elixirforum.com/t/load-module-during-test/7400
It turns out there is a variable in the "Mix.Project" that specifies the paths for the sources:
So in my "mix.exs" I did the following:
def project do
[
...
elixirc_paths: elixirc_paths(Mix.env),
...
]
end
defp elixirc_paths(env_name) do
case env_name do
:test -> ["lib", "test/mockery"]
_ -> ["lib"]
end
end
Of course I added the directory "test/mockery/" and moved "MyApp.MyServiceMock" there...