Search code examples
elixirphoenix-frameworkecto

Ecto.NoResultsError in controller test


In my phoenix controller I use:

...
def delete(conn, %{"id" => id}) do
    post = Repo.get!(Post, id)
    with {:ok, %{post: %Post{}}} <- Posts.delete_post(post) do
        send_resp(conn, :no_content, "")
    end
end
...

in my test:

...
test "deletes chosen post", %{conn: orig_conn, user: user, post: post} do
  conn = delete orig_conn, v1_post_path(orig_conn, :delete, post)
  assert response(conn, 204)
  conn = delete orig_conn, v1_post_path(orig_conn, :delete, post)
  assert response(conn, 404)
end
...

but this test fails when the post does not exist:

...
** (Ecto.NoResultsError) expected at least one result but got none in query:
...

Why? as I see this, Ecto.NoResultsError should return the status of 404

Phoenix version 1.3, phoenix-ecto 3.3, ecto 2.1


Solution

  • By default, Phoenix configures your test environment to render errors for exception. This is on purpose, otherwise a bug in your code would become a 500 page in your tests, and you would have to trace that back. That's why you get an exception.

    Luckily, for the cases you want to check which status code you would get for such exceptions, there is assert_error_sent:

    assert_error_sent :not_found, fn ->
      get build_conn(), "/users/not-found"
    end
    
    assert_error_sent 404, fn ->
      get build_conn(), "/users/not-found"
    end