我正在构建一个以特定顺序发送消息的Elixir模块。我写了像这样的单元测试
MyModule.send_msgs(self())
assert_received {:event, 1}
assert_received {:event, 2}
assert_received {:event, 3}
问题是,即使我改变了assert_received
命令,测试仍然通过。
MyModule.send_msgs(self())
assert_received {:event, 2}
assert_received {:event, 1}
assert_received {:event, 3}
似乎assert_received
并不关心邮件到达的顺序。不仅仅是assert_received
,据我所知,receive
也可能无法收到消息。
所以,我的问题是,如果收到的消息可以无序接收,你如何确保到达消息的顺序?
答案 0 :(得分:7)
这似乎不是一个现有的功能,但是很容易制作自己的宏,它断言邮箱中的下一条消息与特定模式匹配:
defmacro assert_next_receive(pattern, timeout \\ 100) do
quote do
receive do
message ->
assert unquote(pattern) = message
after unquote(timeout) ->
raise "timeout" # you might want to raise a better message here
end
end
end
测试:
defmodule MTest do
use ExUnit.Case
def send_msgs(pid) do
send pid, {:event, 1}
send pid, {:event, 2}
send pid, {:event, 3}
end
defmacro assert_next_receive(pattern, timeout \\ 100) do
quote do
receive do
message ->
assert unquote(pattern) = message
after unquote(timeout) ->
raise "timeout" # you might want to raise a better message here
end
end
end
test "should pass" do
send_msgs(self())
assert_next_receive {:event, 1}
assert_next_receive {:event, 2}
assert_next_receive {:event, 3}
end
test "should fail" do
send_msgs(self())
assert_next_receive {:event, 1}
assert_next_receive {:event, 3}
assert_next_receive {:event, 2}
end
end
输出:
.
1) test should fail (MTest)
test/m_test.exs:29
match (=) failed
code: {:event, 3} = message
right: {:event, 2}
stacktrace:
test/m_test.exs:32: (test)
Finished in 0.05 seconds
2 tests, 1 failure
Randomized with seed 351622