如何调试Elixir ExUnit中assert_receive无匹配消息问题?
调试ExUnit测试中未匹配消息的问题
遇到这种超时没收到预期消息的情况,咱们可以分几步来排查,先搞清楚实际收到了什么,再一步步定位问题:
1. 先看看实际收到的消息是什么
最直接的方法是修改测试代码,捕获所有发送给测试进程的消息,而不是只等预期的那一条。比如把原来的assert_receive替换成下面的代码:
test "make request, report results, then terminates" do ref = make_ref() {:ok, pid} = WolFram.start_link("1 + 1", ref, self(), 1) # 先等一小会儿,确保消息有时间发送过来 Process.sleep(200) # 打印当前测试进程的所有消息队列 IO.inspect(Process.info(self(), :messages), label: "📥 Received messages") # 或者用receive捕获任意一条消息 receive do msg -> IO.inspect(msg, label: "⚠️ Got unexpected message") after 100 -> IO.puts("❌ No message received at all") end end
运行测试后,你就能清楚看到:到底是完全没收到消息,还是收到的消息格式/内容和预期不符(比如ref不对、消息原子是:result而不是:results、Result结构体的字段不对等)。
2. 排查常见的低级错误
先检查最容易忽略的细节:
- 模块别名拼写错误:你的测试里写的是
alias InfoSys.WolFram,但模块定义是InfoSys.Backends.Wolfram——注意Wolfram的f是小写,你写成了大写F!这会导致你调用的是一个不存在的模块,自然不会有消息发送过来。这是非常常见的笔误,先确认这个点。 - 超时时间太短:你给的超时参数是
1(单位应该是秒?),如果Wolfram请求需要更长时间才能返回,进程还没处理完就超时终止了,自然发不出消息。可以把超时调大到5试试。 - 进程是否崩溃:可以给进程加个监视器,看看它是不是异常终止了:
test "make request, report results, then terminates" do ref = make_ref() {:ok, pid} = WolFram.start_link("1 + 1", ref, self(), 5) monitor_ref = Process.monitor(pid) receive do {:DOWN, ^monitor_ref, :process, ^pid, reason} -> IO.inspect(reason, label: "💥 Process crashed with reason") msg -> IO.inspect(msg, label: "📥 Received message") after 2000 -> IO.puts("⏰ No message or crash received") end end
3. 深入调试后端代码
如果上面的步骤还没找到问题,就需要看看Wolfram后端的代码逻辑:
- 加日志输出:在
InfoSys.Backends.Wolfram模块的关键位置加IO.inspect,比如启动函数、请求处理函数、发送消息的地方,看看请求有没有被正确处理,消息有没有按预期生成并发送:
defmodule InfoSys.Backends.Wolfram do def start_link(query, ref, owner, timeout) do IO.inspect({query, ref, owner, timeout}, label: "🚀 Starting Wolfram request") # 原有启动逻辑 end # 假设处理完请求后发送消息的函数 defp send_results(ref, owner, result) do msg = {:results, ref, [result]} IO.inspect(msg, label: "📤 Sending message to owner") send(owner, msg) end end
- 使用Elixir调试器:启动自带的调试器,一步步跟踪代码执行:
# 在iex里启动调试器 :debugger.start() # 把Wolfram模块加入调试 :int.ni(InfoSys.Backends.Wolfram) # 设置断点,比如在start_link函数上 :int.break(InfoSys.Backends.Wolfram, :start_link, 4)
然后运行测试,就能一步步看代码执行到哪一步出了问题。
内容的提问来源于stack exchange,提问作者lapinkoira
相关产品推荐
相关产品推荐

