[erlang-questions] Mocks and explicit contracts

Roger Lipscombe roger@REDACTED
Thu Nov 19 13:36:21 CET 2015


In http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/,
José Valim suggests a way to use dependency injection to more easily
unit test Elixir code.

However, it doesn't translate to Erlang...

In one example, he stores the dependency (as a module) in the
application environment and then defines a private function to
retrieve it:

    defp twitter_api do
        Application.get_env(:my_app, :twitter_api)
    end

Then it can be called as:

    twitter_api.get_username(username)

This doesn't translate to Erlang (or, rather, it's unwieldy), because
we can't do the following:

    twitter_api() ->
        application:get_env(my_app, twitter_api, default_twitter_api).

    show(Username) ->
        % syntax error before: ':'
        twitter_api():get_username(Username)
        etc.

We need more brackets:

        (twitter_api()):get_username(Username)

This gets a bit ugly, though less so with macros:

    -define(TWITTER_API,
        % note the extra brackets:
        (application:get_env(my_app, twitter_api, default_twitter_api))).

    show(Username) ->
        ?TWITTER_API:get_username(Username).

He goes on to show another form of DI which takes advantage of the
fact that Elixir allows inline modules, Again, we can't do this in
Erlang.

So:
- Is Jose's approach applicable to Erlang at all?
- Are there idiomatic ways to do something like this in Erlang?

I know about (and use) 'meck', which is awesome, but has the
disadvantage that it mocks (verb) globally, which limits running tests
in parallel. It can also be quite slow, because it compiles the mocks
on the fly. José's approach uses mocks (noun) locally.



More information about the erlang-questions mailing list