al_*_*al_ 5 testing functional-programming elixir ex-unit
我有一个我想测试的Elixir程序,它可以通过IO.gets多次从用户那里获得输入.我如何在测试中伪造这个输入?
注意:我想为每个返回不同的值 IO.gets
这样做的首选方法是将代码分为纯(无副作用)和不纯(io).所以,如果您的代码如下所示:
IO.gets
...
...
...
IO.gets
...
...
Run Code Online (Sandbox Code Playgroud)
尝试将IO.gets之间的部分提取到可以单独测试的函数中IO.gets:
def fun_to_test do
input1 = IO.gets
fun1(input1)
input2 = IO.gets
fun2(input2)
end
Run Code Online (Sandbox Code Playgroud)
然后你可以单独测试这些功能.这并不总是最好的事情,尤其是不纯的部分是内心深处if,case或cond语句.
另一种方法是将其IO作为显式依赖项传递:
def fun_to_test(io \\ IO) do
io.gets
...
...
...
io.gets
...
...
end
Run Code Online (Sandbox Code Playgroud)
这样您就可以在不做任何修改的情况下从生产代码中使用它,但在测试中,您可以将它传递给一些不同的模块fun_to_test(FakeIO).如果提示不同,您可以只对gets参数进行模式匹配.
defmodule FakeIO do
def gets("prompt1"), do: "value1"
def gets("prompt2"), do: "value2"
end
Run Code Online (Sandbox Code Playgroud)
如果它们始终相同,则需要保持gets被调用次数的状态:
defmodule FakeIO do
def start_link do
Agent.start_link(fn -> 1 end, name: __MODULE__)
end
def gets(_prompt) do
times_called = Agent.get_and_update(__MODULE__, fn state ->
{state, state + 1}
end)
case times_called do
1 -> "value1"
2 -> "value2"
end
end
end
Run Code Online (Sandbox Code Playgroud)
最后一个实现是一个完全工作的模拟及其内部状态.FakeIO.start_link在测试中使用它之前需要调用.如果这是你需要在许多地方做的事情,你可以考虑一些模拟库,但正如你所看到的 - 这不是太复杂.为了FakeIO做得更好,您可以打印提示.我在这里略过了这个细节.
| 归档时间: |
|
| 查看次数: |
512 次 |
| 最近记录: |