Fl4m3Ph03n1x
How to test a behaviour with function macros?
Background
I have a behaviour that has some functions inside it, so that modules that implement it can use them:
defmodule MyBehaviour do
#some callback for other modules to implement
@callback match(data :: any) :: boolean
defmacro __using__(_opts) do
quote do
@behaviour MyBehaviour
def build_query(some_str) do
String.slice(some_str, 1..-1) #random op on string
end
end
end
end
Problem
However, I need to test if build_query is working properly. I can’t invoke it and test it normally via MyBehaviour.build_query/1 because technically it doesn’t belong to the behaviour, it is instead inside the macro.
Question
How do I access MyBehaviour.build_query/1 in order to test it?
Marked As Solved
NobbZ
defmodule FooTest do
defmodule FakeImplementor do
use MyBehaviour
end
test "build the query" do
# whatever is necessary to check `build_query/1` by calling it through `FakeImplementor`
end
end
This is one way.
The other way (which I’d prefer) were to not inject it, but import it and also make it unimportable through options.
Also Liked
NobbZ
The default implementations are not tested at all, they just logg if they were called to avoid a spilling message queue, as soon as you see such a message in production, you should implement a proper handler that deals with those messages. If you have at least one handle_X, the default one isn’t used any more and your GenServer would crash on an unknown message for that handler.
child_spec is probably not tested as well, it just returns a constant map and doesn’t change.
If at all you’d test the __using__ macro if it creates the child_spec function correctly, as you need to specify some things that child_spec shall return as an argument to the use.
NobbZ
I’m not aware of the community opinion, but I hate everything that pollutes my namespace without giving me the option to surpress this polution.
I can cope with overridable default implementations, but for helper functions I prefer if they are in their own namespace.
But that is my personal opinion, the community might see it differently.








