为什么我的 ErrorView 没有在测试中呈现?

Why isn't my ErrorView rendering in tests?

我目前正在尝试测试我的控制器的更新功能,它看起来像这样:

def update(conn, params = %{"id" => id}) do
  lesson_params = Map.delete(params, "id")
  lesson = Lessons.get_lesson!(id)
  with {:ok, %Lesson{} = lesson} <- Lessons.update_lesson(lesson, lesson_params) do
    json(conn, LessonSerializer.to_map(lesson))
  end
end

我的更新 404 测试出现故障的地方。当我调用控制器函数时,我得到一个 Ecto.NoResultsError 落空。

put(build_conn(), lesson_path(build_conn(), :update, Ecto.UUID.generate), %{})

据我所知,我的 ErrorView 应该已经启动以呈现正确的响应,但在我的测试环境中似乎并没有发生。相反,异常会一直下降。当我将 debug_errors 设置为 false.

时,我的 ErrorViewdev 中工作正常

ErrorView 应该在测试中工作吗?还是我在这里遗漏了什么?如果这是预期的,是否有任何方法可以为测试启用 ErrorView

我认为 Phoenix 不会呈现错误视图,除非您告诉它。

我个人不喜欢“未找到则提出”方法,但我认为您必须 try/rescue 并显式呈现错误视图。另一种方法是使用查询的“非爆炸”版本(即:get 而不是 get!)并在得到 nil 时呈现错误视图。

您可以使用一点“魔法”:FallbackController。你用 action_fallback/1 连接它。文档很好地涵盖了这一点,包括 FallbackController 的示例实现:

https://hexdocs.pm/phoenix/Phoenix.Controller.html#action_fallback/1

基本上,您的 with 块会尝试匹配“ok 元组”,它会 return 得到不匹配的任何内容(而不是抛出不匹配错误) . Phoenix 期望 return a conn 的动作,所以连接 action_fallback 告诉它如果没有得到 conn 应该做什么。

我认为您需要将 Lessons.update_lesson/2 更改为 return 一个错误而不是引发...类似 {:error, :not_found} 的内容将是标准做法,并且在文档。

请注意,一般来说,您只需制作一个 FallbackController,您的所有控制器都使用它来处理它们的错误情况。