Hello,
I am working on an existing Phoenix project. So far a lot of 404 pages were handled manually with code that would look like
case Repo.get(Dataset, id) do
dataset -> / do stuff
nil -> / answer with a 404
end
Now I’ve found that there is a way to handle that automatically with phoenix_ecto, using its Plug.Exception. I have added the dependency as described on the project page and am happy because I can now write code like this :
Repo.get!(Dataset, id)
and in case the query fails, a %Ecto.NoResultsError
is raised and the error is converted automatically to a 404 response, and I get the desired result.
Now I’m trying to test that behavior using the assert_error_sent
macro like this :
test "unexisting dataset", %{conn: conn} do
assert_error_sent(404, fn -> get(conn, dataset_path(conn, :details, "yo")) end)
end
I have reduced the details
function to :
def details(%Plug.Conn{} = conn, %{"slug" => slug}) do
dataset = Repo.get_by!(Dataset, slug: slug)
text(conn, "hello #{dataset.id}")
end
I run the test with MIX_ENV=test mix test
and it fails, telling me that
1) test details unexisting dataset (TransportWeb.DatasetControllerTest)
apps/transport/test/transport_web/controllers/dataset_controller_test.exs:14
expected error to be sent as 404 status, but got an error with no response from:
** (Protocol.UndefinedError) protocol Phoenix.HTML.Safe not implemented for %Ecto.NoResultsError{message: "expected at least one result but got none in query:\n\nfrom d0 in DB.Dataset,\n where: d0.slug == ^\"yo\"\n"} of type Ecto.NoResultsError (a struct). This protocol is implemented for the following type(s): Phoenix.LiveView.Rendered, Phoenix.LiveView.Comprehension, Atom, DateTime, List, Phoenix.HTML.Form, Integer, Float, BitString, NaiveDateTime, Date, Time, Tuple
code: assert_error_sent(404, fn -> get(conn, dataset_path(conn, :details, "yo")) end)
stacktrace:
(phoenix_html) lib/phoenix_html/safe.ex:1: Phoenix.HTML.Safe.impl_for!/1
(phoenix_html) lib/phoenix_html/safe.ex:15: Phoenix.HTML.Safe.to_iodata/1
(transport) lib/transport_web/templates/error/internal_server_error.html.eex:3: TransportWeb.ErrorView."internal_server_error.html"/1
(transport) lib/transport_web/templates/layout/app.html.eex:61: TransportWeb.LayoutView."app.html"/1
(phoenix) lib/phoenix/view.ex:410: Phoenix.View.render_to_iodata/3
(phoenix) lib/phoenix/controller.ex:729: Phoenix.Controller.__put_render__/5
(phoenix) lib/phoenix/endpoint/render_errors.ex:77: Phoenix.Endpoint.RenderErrors.instrument_render_and_send/5
(phoenix) lib/phoenix/endpoint/render_errors.ex:62: Phoenix.Endpoint.RenderErrors.__catch__/5
(phoenix) lib/phoenix/test/conn_test.ex:235: Phoenix.ConnTest.dispatch/5
(phoenix) lib/phoenix/test/conn_test.ex:671: Phoenix.ConnTest.wrap_request/1
(phoenix) lib/phoenix/test/conn_test.ex:625: Phoenix.ConnTest.assert_error_sent/2
test/transport_web/controllers/dataset_controller_test.exs:15: (test)
If I access the same page manually, I get a 404 response. I can’t understand why Plug.Exception is having no effect when tests are run.
Could somebody help me ?
Thanks !