我有一个要测试的Elixir程序,它需要IO.gets
多次从用户那里获取输入。我将如何在测试中伪造此输入?
注意:我想为每个返回不同的值 IO.gets
首选的方法是将代码分为纯代码(无副作用)和不纯代码(做io)。因此,如果您的代码如下所示:
IO.gets
...
...
...
IO.gets
...
...
尝试将IO.gets之间的部分提取为可以独立于进行测试的功能IO.gets
:
def fun_to_test do
input1 = IO.gets
fun1(input1)
input2 = IO.gets
fun2(input2)
end
然后您可以单独测试功能。这并不总是最好的事情,尤其是不纯的部分是内心深处if
,case
或cond
语句。
替代方法是将传递IO
为显式依赖项:
def fun_to_test(io \\ IO) do
io.gets
...
...
...
io.gets
...
...
end
这样,您可以直接在生产代码中使用它,而无需进行任何修改,但是在测试中,您可以将其传递给其他模块fun_to_test(FakeIO)
。如果提示不同,则可以对gets
参数进行模式匹配。
defmodule FakeIO do
def gets("prompt1"), do: "value1"
def gets("prompt2"), do: "value2"
end
如果它们始终相同,则需要保持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
最后一个实现是一个具有内部状态的完全可用的模拟。您需要先致电FakeIO.start_link
才能在测试中使用它。如果这是您需要在许多地方执行的操作,则可以考虑使用一些模拟库,但是正如您所看到的-这并不太复杂。为了FakeIO
更好,您可以打印提示。我在这里跳过了这个细节。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句