Testing conn helpers in isolation?

Let’s say I have a helper function called not_found/1, which looks something like:

def not_found(conn) do
	conn
	|> put_status(404)
	|> put_view(MyApplication.ErrorView)
	|> render(:"404")
	|> halt()
end

This is a very trivial example to show the idea. Now I wonder how to test such things in isolation? Like how would setup / assertions need to look like.

Hey @silverdr, what have you tried so far?

You can use Phoenix.ConnTest helpers to build a connection, run it through the helper and then make assertions on the content of the resulting Plug.Conn.

But I’d consider writing a more “end-to-end” test: write some test code that uses the helper the same way your production code does and then assert on the results. From the looks of it, it would mean writing a test controller.

I agree that for such simplified example it doesn’t add much value to test it in isolation. I am looking for a “methodology” of testing such functions in general though. Especially when they’re complex enough to justify “unit testing” them separately.

Something akin to that should work in a normal phoenix MyAppWeb.ConnCase module:

    test "no header" do
      conn = build_conn(:get, "/")

      conn = call_plug(conn, [])

      assert conn.status == 403
      assert conn.state == :sent
      assert conn.halted
    end
1 Like

How is this defined? Is use MyAppWeb.ConnCase enough to qualify? Asking because I wrote now quickly a testmodule:

defmodule MyAppWeb.HelpersTest do
	use MyAppWeb.ConnCase, async: true

	alias MyAppWeb.Helpers

	describe "not_found/1" do
		test "reponds with 404" do
			conn = build_conn(:get , "/")
			conn = Helpers.not_found(conn)
			assert conn.status == 404
		end
	end
end

and that gives ** (ArgumentError) cannot fetch key "_format" from conn.params because they were not fetched. Configure and invoke Plug.Parsers to set params based on the request

Yeah, that was a “typo” on my part.

build_conn gives you a “bare” conn. Your plug requires a format to be available on the conn (when using render with an atom), so you need to set a format on the conn as well: conn = put_format(conn, "html"). Usually this is set by the Phoenix.Controller.accepts/2 plug in your router pipeline.

1 Like

@LostKobrakai 🙇‍♂️