在Elixir中测试异步代码 [英] Testing asynchronous code in Elixir
问题描述
我想测试使用 Task.async
的功能,以便通过测试,我需要在声明前使其休眠100毫秒,否则测试过程将在执行异步任务之前终止。
In order to make my test pass, I need to make it sleep for 100ms before assertions, otherwise the test process is killed before the async task is executed.
有没有更好的方法?
编辑,添加代码示例:
我想测试的代码(大致):
The code I would like to test (roughly) :
def search(params) do
RateLimiter.rate_limit(fn ->
parsed_params = ExTwitter.Parser.parse_request_params(params)
json = ExTwitter.API.Base.request(:get, "1.1/search/tweets.json", parsed_params)
Task.async(fn -> process_search_output(json) end)
new_max_id(json)
end)
end
我已经编写的测试(仅适用于睡眠调用)。
And the test I already wrote (working only with the call to sleep)
test "processes and store tweets" do
with_mock ExTwitter.API.Base, [request: fn(_,_,_) -> json_fixture end] do
with_mock TwitterRateLimiter, [rate_limit: fn(fun) -> fun.() end] do
TSearch.search([q: "my query"])
:timer.sleep(100)
# assertions
assert called TStore.store("some tweet from my fixtures")
assert called TStore.store("another one")
end
end
end
推荐答案
由于问题有点含糊,我在这里给出一般性的答案。通常的技术是监视过程并等待出现故障消息。像这样:
Since the question is a bit vague, I will give the general answer here. The usual technique is to monitor the process and wait for the down message. Something like this:
task = Task.async(fn -> "foo" end)
ref = Process.monitor(task.pid)
assert_receive {:DOWN, ^ref, :process, _, :normal}, 500
一些重要的事情:
-
元组的第五个元素是退出原因。我声称任务出口为
:normal
。如果您期望另一个出口,请相应地进行更改。
The fifth element of the tuple is the exit reason. I am asserting the Task exit is
:normal
. Change that accordingly if you are expecting another exit.
assert_receive
中的第二个值是超时。假设您目前有100毫秒的睡眠时间,那么500毫秒听起来是一个合理的数目。
The second value in assert_receive
is the timeout. 500 miliseconds sounds like a reasonable amount given you currently have a 100 ms sleep.
这篇关于在Elixir中测试异步代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!