dashbitco / mox

Mocks and explicit contracts in Elixir
1.35k stars 77 forks source link

How should I wire up mox when writing a library? #60

Closed andrewjensen closed 5 years ago

andrewjensen commented 5 years ago

Hi friends! I am working on implementing mox inside of a library at work, and I ran into problems with wiring up mox.

I had code like this to reference my implementation in prod code:

defmodule Datemath.Interpreter do
  # ...

  @relative_date Application.get_env(:datemath, :relative_date_impl)

  defp evaluate_date_relative() do
    @relative_date.now()
  end
end

And I had config like this to provide either the real implementation or the mock:

# config.exs:
config :datemath,
  relative_date_impl: Datemath.Interpreter.RelativeDateResolver

# dev.exs
config :datemath,
  relative_date_impl: Datemath.Interpreter.RelativeDateMock

But when I imported my library into my app and hit the Datemath.Interpreter.evaluate_date_relative function, I got an error saying nil.now was undefined. My config did not take effect in an app.

The workaround I found was to call get_env with a default provided as a third parameter:

@relative_date Application.get_env(:datemath, :relative_date_impl, Datemath.Interpreter.RelativeDateResolver)

This worked because the library will use its config while in dev or test, and apps that consume the library will fall back to the default implementation.

But is there a better way to do this? Thanks!

josevalim commented 5 years ago

You have to set the default value inside the :env key in def application in your mix.exs file. The values in config are never loaded from libraries, to avoid libraries messing up the global configuration. --

José Valim www.plataformatec.com.br Skype: jv.ptec Founder and Director of R&D