@andreaseriksson yeah, that’s what we tried but the handle_info/2 function has the arguments msg, socket and we could not figure out how to create a mock socket because conn does not appear to work.
Our test is:
test "handle_info/2", %{conn: conn} do
msg = %{payload: %{ val: 1 }}
{:noreply, result} = LiveViewCounterWeb.Counter.handle_info(msg, conn)
assert result == %{val: 1}
end
But we get the following error:
1) test handle_info/2 (LiveViewCounterWeb.CounterTest)
test/live_view_counter_web/live/counter_test.exs:29
** (FunctionClauseError) no function clause matching in Phoenix.LiveView.assign/2
The following arguments were given to Phoenix.LiveView.assign/2:
# 1
%Plug.Conn{adapter: {Plug.Adapters.Test.Conn, :...}, assigns: %{}, before_send: [], body_params: %Plug.Conn.Unfetched{aspect: :body_params}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "www.example.com", method: "GET", owner: #PID<0.358.0>}
# 2
[val: 1]
Attempted function clauses (showing 1 out of 1):
def assign(%Phoenix.LiveView.Socket{} = socket, attrs) when is_map(attrs) or is_list(attrs)
code: {:noreply, result} = LiveViewCounterWeb.Counter.handle_info(msg, conn)
stacktrace:
(phoenix_live_view 0.10.0) lib/phoenix_live_view.ex:1475: Phoenix.LiveView.assign/2
(live_view_counter 0.10.0) lib/live_view_counter_web/live/counter.ex:25: LiveViewCounterWeb.Counter.handle_info/2
test/live_view_counter_web/live/counter_test.exs:31: (test)
That won’t test anything since send/2 returns the argument, so this assertion does not exercise any handling in the LV.
You also do not want to unit test the callbacks as that is very brittle and does not exercise the stateful LV. Aside: I also never unit tests GenServer’s in this way. For your test, you can send the message, and then assert the rendered LV content is what you expect after it experiences the side effects. This works because LiveViewTest.render/1 sends a message to the LV process to synchronize with it, which guarantees it has already processed the send:
Hi Chris!
Thanks for chiming in on this noob question
and clarifying that send/2 simply returns message so it’s not really testing anything.
Our understanding was that invoking send(view.pid, msg) would in turn call handle_info/2, but your suggested test is much better as it actually renders the LiveView and makes an assertion about the state of the counter.
send does send a message to the pid. That’s all it does and knows about. How the receiving process handles the message happens completely async and is up to the receiver alone.