Define a constant module in elixir

≡放荡痞女 提交于 2019-12-11 13:40:56

问题


I would like to create some changeable boundary module. Ideally the result would look like any other module but the behaviour could be set at compile time or in the configuration files. I think I am looking for something like define in erlang

Say I have a SystemClock module and a DummyClock tuple module. Ideally the Clock module would be one or other of the two modules above chosen in the config file.

In config/test.ex

define(Clock, {DummyClock, 12345678})

Later

Clock.now
# => 12345678

In config/prod.ex

define(Clock, SystemClock)

Later

Clock.now
# => 32145687

回答1:


I think the easiest way to do this is with configs and Application.get_env/2.

in config/test.exs

config :my_application, clock: DummyClock

in config/dev.exs and config/prod.exs

config :my_application, clock: RealClock

in the code that uses the clock

defp clock, do: Application.get_env(:my_application, :clock)

def my_function(arg1, arg2) do
  now = clock.now
  # ...
end



回答2:


An option that I've used many times is Meck, which you can get/read about here. For your example, we might write something like:

test "something that depends on Clock calls Clock.now" do
  :meck.new(Clock, [])
  :meck.expect(Clock, :now, fn -> 12345678 end)

  # we expect that the module under test is getting it's result from Clock
  assert ModuleUnderTest.execute  == 12345678
end

Instead of re-compiling your code to get :test behavior, Meck replaces the functionality of your modules on the fly, during your tests.

The discussion referenced in other comments here points out some reasons not to use mocking; Yes, you have to sacrifice certain things (sequential testing, and José's opinion of your testing code), but in exchange, you can dramatically simplify testing code in tricky situations.



来源:https://stackoverflow.com/questions/32860342/define-a-constant-module-in-elixir

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!