I am using elixir and following the advice from the http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/ blog post.
I have run into a problem of tracking which mock function corresponds to which test. I added a mock module for the test environment for an api wrapper. As I add mock functions to the mock api module, I have found that I dont remember which functions were written to return results for which tests.
I have been trying to figure out a way to use a macro to define the mocked method near the test. I am also interested in this question as a learning exercise.
Below is how I would envision it to work:
defmodule SomeMockModule do
end
defmodule MockUtil do
defmacro add_mock module, block do
# <THE MISSING PIECE>
end
end
defmodule Test do
use ExUnit.Case
require MockUtil
MockUtil.add_mock SomeMockModule do
def some_func do
"mock value"
end
end
test "The mock value is returned" do
assert SomeMockModule.some_func == "mock value"
end
end
This is similar to the question about open modules: Open modules in Elixir? however I am wondering about how to do it at compile time not runtime.
I have looked around and I have not found anything that says it can or cannot be done at compile time.
In a way this is a fancy copy and paste :)
What I have tried so far:
1) The following works but seems rather messy. and it requires changes to the mock module. I am trying to figure out if there is a way to do it without the before compile.
defmodule MockUtil do
defmacro register_function( _module, do: block )do
Module.put_attribute Test, :func_attr, block
end
end
defmodule Test do
require MockUtil
Module.register_attribute __MODULE__,
:func_attr,
accumulate: true, persist: false
defmacro define_functions(_env) do
@func_attr
end
MockUtil.register_function SomeMockModule do
def foo_bar do
IO.puts "Inside foo_bar."
end
end
end
defmodule SomeMockModule do
@before_compile {Test, :define_functions}
end
SomeMockModule.foo_bar
2) I also tried, in the place of :
Module.eval_quoted module, block
however it throws an error:
could not call eval_quoted on module {:__aliases__, [counter: 0, line: 10], [:SomeMockModule]} because it was already compiled
I guess I am running into order of compile issues.
Is there a way to add a function to a module at compile time?