Dynamically apply method from Phoenix.ConnTest

I’m in the process of creating some reusable test modules using a macro:

defmodule SharedTestCase do
  defmacro define_tests(do: block) do
    quote do
      defmacro __using__(options) do
        block = unquote(Macro.escape(block))

        quote do
          use ExUnit.Case

          @moduletag unquote(options)

I’ve gotten as far as defining a reusable method for post/3 requests, but would like to extend to supply the verb as a method. I’m unsure how to invoke the methods supplied by Phoenix.ConnTest dynamically as Kernel.apply/3 expects a module as the first argument. Here is a working example for post requests:

defmodule EnsureAuthenticatedConnTests do
  import SharedTestCase

  define_tests do
    test "returns an error when the connection has no form of authentication", %{data: data, route: route} do
      assert %{
        "errors" => [%{
          "message" => "Unauthorized"
      } == build_conn()
      |> put_req_header("accept", "application/json")
      |> post(route, data)
      |> json_response(401)

Ideally, post becomes a method invoked by Kernel.apply/3. Using the module:

defmodule MyApp.SomeControllerTest do
  use MyApp.ConnCase

  use EnsureAuthenticatedConnTests, data: %{"foo" => "bar}, route: "/users"

Any thoughts would be appreciated!

1 Like

A minor note: if this is like the conn_case.ex file generated by the Phoenix installer, it’s already doing things like use ExUnit.Case via ExUnit.CaseTemplate

You likely have alias MyApp.Repo in your conn_case.ex file.

Just change it to alias MyApp.Repo, warn: false if you want a quick solution.

I’m not sure that I follow – I’m asking about using autogenerated methods in Phoenix.ConnTest to do some meta-programming

Well I could swear my comment looked relevant when I posted it. :003:

Sorry for the noise. Right now I have no good idea how to do your thing.

Felt so bad that I posted in the wrong thread here so I came back: OP, did you solve your problem?

1 Like