2016-09-29 63 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