2016-09-29 62 views
3

试图学习使用elixir进行基本代码测试,并在测试异步函数(genserver的handle_info和cast)时遇到麻烦。GenServer异步集成测试

工作但感觉不对的一种方法是在投射异步函数后使用:timer.sleep(x)

例如,假设handle_cast正在处理来自状态的项目列表,并将调用分派到另一个将从外部API获取数据的模块,并且完成后它将发送消息(api数据)回到同一个genserver。

什么是最好的测试方法?我可以在测试中监控genserver邮件/邮箱吗?

编辑: 另一个例子,说在初始化我这样做是为了从数据库获取初始状态:

Process.send_after(self(), :started, 0) 

和:开始看起来像:

defhandleinfo :started, state: state, do: new_state(UserServerStarted.get_data(state)) 

我是否有任何其他选项然后:timer.sleep检查UserServerStarted是否返回正确的东西?我知道我可以单独测试该模块/单元,但我想进行完整的集成测试。

以下就是我正在做的现在:

... SETUP - Supervisor start UserServer... 

    test "spin up server and inital tree after user registers", % 
    {user: user} do 
    :timer.sleep(500) 
    assert %{"default" => [nil]} == GenServer.call(UserServer.via_tuple(user.id), :get) 
    end 
+0

您可以使用get邮箱的邮件'Process.info(PID ,:messages)'但是这不能可靠地与GenServer一起工作,因为GenServer一收到它就会处理消息,除非它忙于处理先前的消息。 – Dogbert

回答

2

我有一个类似的问题最近挣扎。我设法通过注册,我想保留在测试轨道的过程中去解决它:

defmodule Foo 
    def bar do 
    pid = spawn fn -> consume(channel, tag, payload) end 
    if !Process.whereis(:worker) do 
     Process.register(pid, :worker) 
    end 
    end 
end 

并在测试:

test "bar" do 
    # < Setup code that triggers your process under test goes here > 

    # I put this here because I noticed that sometimes the process would not be 
    # fast enough to be registered - this was a quick fix. 
    :timer.sleep(100) 

    ref = Process.monitor(Process.whereis(:worker)) 

    # assert_receive will block the test until your registered process exits, 
    # or 10 seconds have passed (then something is wrong with the external service perhaps and the test will fail) 
    assert_receive {:DOWN, ^ref, :process, _, :normal}, 10000 

    # At this point the process has exited, continue with whatever assertions you want to make 
end