defp
定义的函数不会导出,因此我无法在模块以外的位置执行它们。
答案 0 :(得分:82)
不,没有办法通过ExUnit测试它们。
我个人避免测试私有函数,因为通常您最终会测试实现而不是行为,并且一旦您需要更改代码,这些测试就会失败。相反,我通过公共函数测试预期的行为,以小的,一致的块来打破它们。
答案 1 :(得分:11)
在您的模块定义中,您可以使用@compile
指令在测试环境中仅导出 私有函数。
defmodule Foo do
@compile if Mix.env == :test, do: :export_all
# This will be exported for tests
defp bar() do
... code ...
end
end
答案 2 :(得分:6)
可以使用宏来改变功能的可见性,具体取决于环境:
defmacro defp_testable(head, body \\ nil) do
if Mix.env == :test do
quote do
def unquote(head) do
unquote(body[:do])
end
end
else
quote do
defp unquote(head) do
unquote(body[:do])
end
end
end
end
然后您可以按如下方式向测试公开函数:
defp_testable myfunc do
...
end
我建议谨慎使用这个问题,理由是José的回答。它不能替代测试模块的外部行为。不过,它在某些情况下可能很有价值。
(Source)
答案 3 :(得分:0)
即使在使用ExUnit进行测试的情况下,也无法从其模块外部调用私有函数。
其他人建议了公开私有功能以进行测试的复杂方法,因此我建议另外两个看起来更简单的方法:
1)将要测试的功能公开,但用RedirectMatch 301 ^/faqs/(.+)$ https://www.example.com/$1
进行标记,这意味着它不属于模块的公共API。
2)或者,如果您要测试的功能是@doc false
,则在同一模块中创建一个defp foo
,该模块将接受您想要在测试期间改变的参数,并将其适应于def test_foo
期望,并最终调用foo
。您也只能在这样的测试过程中生成特殊的测试功能
foo
这些替代方案中的任何一个都更简单,并且在项目中不需要任何额外的依赖关系。
当然,正如其他人提到的那样,一般规则是避免测试私有功能,但是有时测试它们是简化测试并扩大测试范围的一种方式。
良好的编码!