** (ArgumentError) cannot convert nil to param

I’m trying to test a session delete action but I can’t manage to make it pass.

Here is the stacktrace I receive

** (ArgumentError) cannot convert nil to param
 stacktrace:
   (phoenix) lib/phoenix/param.ex:67: Phoenix.Param.Atom.to_param/1
   (moosely) web/router.ex:1: Moosely.Router.Helpers.session_path/4
   test/controllers/session_controller_test.exs:48: (test)

Here is my test code

  test "deletes the user session", %{conn: conn} do
    user = Repo.get_by(User, %{username: "test"})
    conn = delete conn, session_path(conn, :delete, user)
    refute get_session(conn, :current_user)
    assert get_flash(conn, :info) == "Signed out successfully!"
    assert redirected_to(conn) == page_path(conn, :index)
  end

And here is the controller action

  def delete(conn, _) do
    conn
    |> delete_session(:current_user)
    |> put_flash(:info, "Signed out successfully!")
    |> redirect(to: page_path(conn, :index))
  end

As a note: the delete action works perfectly, or it looks like so, in the UI but I can’t trust that until I have some tests passing.

it’s a long shot, but is it possible that Repo.get_by(User, %{username: "test"}) returns nil? In cases like that I prefer to call get_by! so that the test will fail early

3 Likes

I piped the result into IO.inspect, it does indeed return nil. Then I used get_by! and I finally understood where the problem was.

I have a setup block in which I define the User object with multiple attributes (such as username, password, email, etc) so the test was expecting the same username as the one I defined in the setup block.

What a rookie mistake, anyway thank you for pointing me towards the right direction!

1 Like

I have a setup block in which I define the User object with multiple attributes (such as username, password, email, etc) so the test was expecting the same username as the one I defined in the setup block.

btw, instead of inserting a record in the setup block and the fetching it in tests, you can pass it around as test context:

setup do
  user = Repo.insert!(%User{...})
  {:ok, %{user: user}}
end

test "some test", c do
  IO.inspect c.user
end

# you can also match on context:

test "some test", %{user: user} do
  IO.inspect user
end
1 Like

This does indeed seem like a better alternative!
I will refactor my tests

1 Like