Testing 在elixir中定义一个常量模块

Testing 在elixir中定义一个常量模块,testing,mocking,elixir,Testing,Mocking,Elixir,我想创建一些可变边界模块。理想情况下,结果看起来像任何其他模块,但行为可以在编译时或在配置文件中设置。我想我正在寻找类似于在erlang中定义的东西 假设我有一个SystemClock模块和一个DummyClock元组模块。理想情况下,时钟模块应该是在配置文件中选择的上述两个模块中的一个或另一个 在config/test.ex中 define(Clock, {DummyClock, 12345678}) define(Clock, SystemClock) 后来 在config/prod.e

我想创建一些可变边界模块。理想情况下,结果看起来像任何其他模块,但行为可以在编译时或在配置文件中设置。我想我正在寻找类似于在erlang中定义的东西

假设我有一个SystemClock模块和一个DummyClock元组模块。理想情况下,时钟模块应该是在配置文件中选择的上述两个模块中的一个或另一个

config/test.ex中

define(Clock, {DummyClock, 12345678})
define(Clock, SystemClock)
后来

config/prod.ex中

define(Clock, {DummyClock, 12345678})
define(Clock, SystemClock)
后来


我认为最简单的方法是使用configs和
应用程序。get_env/2

config/test.exs中

config :my_application, clock: DummyClock
config :my_application, clock: RealClock
config/dev.exs
config/prod.exs

config :my_application, clock: DummyClock
config :my_application, clock: RealClock
在使用时钟的代码中

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

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

我使用过很多次的一个选项是
Meck
,它是。例如,我们可以编写如下内容:

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
在测试过程中,
Meck
动态替换模块的功能,而不是重新编译代码以获得
:test
行为


其他评论中提到的讨论指出了不使用嘲弄的一些原因;是的,您必须牺牲某些东西(顺序测试,以及José对测试代码的看法),但作为交换,您可以在棘手的情况下大大简化测试代码

这是一个很好的答案,但我一直在避免这样做,因为我不想改变现有的代码,并能够使用它作为模拟机制。Ie在应用程序中不应该要求开发人员了解应用程序设置。邮件列表上有一条很长的线索,José解释了为什么您不需要它。从这里开始:我认为在一些地方它们可能非常有用。我提供了一个我今天下午在这里尝试的解决方案的示例,因为在Erlang中定义与在C/C++中定义非常相似。这基本上是字符串替换。