Elixir 中的测试方法委托
Test method delegation in Elixir
我有两个模块:
defmodule Base.ModuleOne do
def do_stuff(opts) do
"some stuff with opts"
end
end
defmodule Base.ModuleTwo do
defdelegate do_stuff(opts), to: Base.ModuleOne
end
不同命名空间下 Base.ModuleOne.do_stuff/1
函数在没有复制粘贴测试的情况下测试委托的正确方法是什么?
截至撰写此答案时,我还没有找到 "official" 方法来测试 defdelegate
。在你的情况下,我能想到的唯一选择是:
- 忽略
Base.ModuleTwo.do_stuff(opts)
的测试,假设您的基础已包含在 Base.ModuleOne.do_stuff(opts)
的测试中。
- 将
Base.ModuleOne.do_stuff(opts)
中的大部分(如果不是全部)测试移至 Base.ModuleTwo.do_stuff(opts)
的测试,这样您的测试就直接与模块的 public 接口相关, 将 Base.ModuleOne
归类为 "private" 实现细节。
- 自 mocking would seem to be generally out of favour in Elixir 起,考虑将
defdelegate
替换为依赖注入(使用函数或模块;有关详细信息,请参阅之前的 link),这样您就可以在以下方式:
模块:
defmodule Base.ModuleTwo do
def do_stuff(opts, dependency \ Base.ModuleOne)
dependency.do_stuff(opts)
end
end
测试:
defmodule ModuleTwoTest do
use ExUnit.Case
describe "Base.ModuleTwo.do_stuff/2" do
defmodule TestDependency do
def do_stuff(_opts) do
send self(), :do_stuff
end
end
test "calls do_stuff/1 on its dependency" do
opts = %{foo: "bar"} # or whatever the `opts` should be
Base.ModuleTwo.do_stuff(opts, TestDependency)
assert_received :do_stuff
end
end
end
我有两个模块:
defmodule Base.ModuleOne do
def do_stuff(opts) do
"some stuff with opts"
end
end
defmodule Base.ModuleTwo do
defdelegate do_stuff(opts), to: Base.ModuleOne
end
不同命名空间下 Base.ModuleOne.do_stuff/1
函数在没有复制粘贴测试的情况下测试委托的正确方法是什么?
截至撰写此答案时,我还没有找到 "official" 方法来测试 defdelegate
。在你的情况下,我能想到的唯一选择是:
- 忽略
Base.ModuleTwo.do_stuff(opts)
的测试,假设您的基础已包含在Base.ModuleOne.do_stuff(opts)
的测试中。 - 将
Base.ModuleOne.do_stuff(opts)
中的大部分(如果不是全部)测试移至Base.ModuleTwo.do_stuff(opts)
的测试,这样您的测试就直接与模块的 public 接口相关, 将Base.ModuleOne
归类为 "private" 实现细节。 - 自 mocking would seem to be generally out of favour in Elixir 起,考虑将
defdelegate
替换为依赖注入(使用函数或模块;有关详细信息,请参阅之前的 link),这样您就可以在以下方式:
模块:
defmodule Base.ModuleTwo do
def do_stuff(opts, dependency \ Base.ModuleOne)
dependency.do_stuff(opts)
end
end
测试:
defmodule ModuleTwoTest do
use ExUnit.Case
describe "Base.ModuleTwo.do_stuff/2" do
defmodule TestDependency do
def do_stuff(_opts) do
send self(), :do_stuff
end
end
test "calls do_stuff/1 on its dependency" do
opts = %{foo: "bar"} # or whatever the `opts` should be
Base.ModuleTwo.do_stuff(opts, TestDependency)
assert_received :do_stuff
end
end
end