patch icon indicating copy to clipboard operation
patch copied to clipboard

Patch GenServer :handle/2 - Idea / question?

Open Matsa59 opened this issue 3 years ago • 1 comments

Hello I have some GenServer that subscribe to Phoenix.PubSub channel to reduce code coupling

I feel like something is missing Patch (that is really nice btw).

My workflow is everytime a character is created, I broadcast a message that will be catch by some GenServers to do their shit (e.g. send welcome email, push discord msg, or log the event in a db or w.e)

I want to test this but because it's a PhoenixPubSub event, it's not easily testable. I end with the following test (that works great).

defmodule ForHonor.Feed.AdventureEventSubscriberTest do
  use Patch
  #...

  test "on character created", %{character: character} do
    patch_handle_info(AdventureEventSubscriber)

    msg = {:character_created, character}
    Phoenix.PubSub.broadcast(ForHonor.PubSub, "game:events", msg)

    assert_handle_info(AdventureEventSubscriber)

    # test if side effect was apply or w.e
  end


  defp patch_handle_info(module) do
    pid = self()

    patch(module, :handle_info, fn msg, state ->
      real(module).handle_info(msg, state)
      |> tap(fn _ -> send(pid, module) end)
    end)
  end

  defp assert_handle_info(module, timeout \\ :timer.seconds(5)) do
    receive do
      ^module -> assert true
    after
      timeout -> assert false
    end
  end
end

I don't have a global overview of patch, maybe I miss something. I would like to have your opinion on the previous code. If their is no other way to accomplish that, are you interested by a pull request ?

Thanks a lot ;)

Matsa59 avatar Feb 19 '22 03:02 Matsa59

I don't see anything obviously wrong with the listing above, but you could simplify the test by using the following pattern.

defmodule ForHonor.Feed.AdventureEventSubscriberTest do
  use Patch
  #...

  test "on character created", %{character: character} do
    spy(AdventureEventSubscriber)

    msg = {:character_created, character}
    Phoenix.PubSub.broadcast(ForHonor.PubSub, "game:events", msg)

    assert_called AdventureEventSubscriber.handle_info(_, _)

    # test if side effect was apply or w.e
  end
end

Depending on the version you were running on there was an issue pre v0.8.0 where patching GenServer would break Patch.

ihumanable avatar Nov 18 '22 00:11 ihumanable