【问题标题】:How to test if msg was send to GenServer process如何测试 msg 是否发送到 GenServer 进程
【发布时间】:2020-10-01 01:50:22
【问题描述】:

我将 GenServer 作为后台作业运行,每个 intervalProcess.send_after(self(), :work, @interval) 重新安排。

此作业由主管在应用程序启动时启动。

它工作得很好,但现在我想测试我的 GenServer 模块是否真的在每个interval 产生新进程。

如何测试它?

编辑

我发现:sys.get_status(pid) 可用于获取有关进程的一些数据,但我真的很想使用receive do ... end 之类的东西

编辑 2

handle_info/2函数:

@impl true
def handle_info(:work, state) do
  do_smt()

  schedule_worker()

  {:noreply, state}
end

schedule_worker/0函数:

defp schedule_worker do
  Process.send_after(self(), :work, @interval)
end

【问题讨论】:

    标签: erlang elixir


    【解决方案1】:

    我将使用Mock library 测试do_smt() 并编写一个如下断言的测试:

    with_mock(MyModule, [do_stm_else: fn -> :ok]) do
       do_smt()
    
       assert_called MyModule.do_stm_else()
    end
    

    这样,您已经调用了任务应该执行的函数,因此您可以假设正在调用任务创建。

    如果您想让do_stm_else 函数与您的测试通信(在这种情况下它看起来有点过度设计),您应该:

    1. 通过调用self()获取测试的pid
    2. 将 pid 传递给模拟函数以使用它
    3. 使用assert_receive 验证通信是否发生
    pid = self()
    
    with_mock(MyModule, [do_stm_else: fn -> 
          Process.send(pid, :msg)
       ]) do
       do_smt()
    
       assert_called MyModule.do_stm_else()
    end
    
    assert_receive(:msg)
    
    

    请注意,我没有时间检查这个,你应该花点时间调查一下。

    【讨论】:

      【解决方案2】:

      您的消息中缺少某些内容。从您发布的内容中,我们可以了解到每@interval 毫秒都会发送一条:work 消息。您没有告诉我们发送消息时handle_info/2 应该做什么。

      一旦定义了这一点,您绝对可以编写一个测试,通过使用assert_received 断言来断言已收到消息。

      【讨论】:

      • 嗨@bruno-ripa,感谢您的回答。我已经通过添加一些代码来更新我的问题:)
      • 因此,假设do_smt() 不相关,您没有生成任何新进程。它总是同一个进程在做某事并安排每个@interval 发送一条消息。我的回答仍然有效;你有几种方法来测试它。您可以决定测试使用assert_received 接收的消息,或者您可以测试do_smt() 的效果是否到位?
      • do_smt() 使用Task.start(fn -> do_stm_else() end) 生成新进程,我想在其他测试中进行测试。你能告诉我如何测试两者吗?
      猜你喜欢
      • 2016-01-12
      • 2019-11-10
      • 1970-01-01
      • 2019-12-05
      • 1970-01-01
      • 2017-06-29
      • 2022-08-22
      • 2017-04-22
      • 1970-01-01
      相关资源
      最近更新 更多