12

我正在用 ecto 编写凤凰应用程序,并在测试中有以下代码段

{:ok, data} = Poison.encode(%{email: "nonexisting@user.com", password: "mypass"})

conn()
|> put_req_header("content-type", "application/json")
|> put_req_header("accept", "application/json")
|> post(session_path(@endpoint, :create), data)
> json_response(:not_found) == %{}

这会引发 Ecto.NoResultsError

我有这个定义

defimpl Plug.Exception, for: Ecto.NoResultsError do
  def status(_exception), do: 404
end

但测试仍然抛出 Ecto.NoResultsError,任何指针?

4

2 回答 2

14

让我们考虑一下它在每个环境中是如何工作的。

  • :prod中,默认是渲染错误页面,所以你应该看到一个YourApp.ErrorView带有状态码的页面;

  • :dev中,默认是显示调试页面,因为大多数时候您在构建代码时都会出错。如果你想看到实际呈现的错误页面,你需要debug_errors: false在你的config/dev.exs;

  • :test中,它像生产环境一样工作,但是因为您是从测试中调用应用程序,所以如果您的应用程序崩溃,您的测试也会崩溃。我们正在对未来的版本进行改进,您应该可以编写如下内容:

    assert_raise Ecto.NoResultsError, fn ->
      get conn, "/foo"
    end
    {status, headers, body} = sent_response(conn)
    assert status == 404
    assert body =~ "oops"
    
于 2015-05-30T07:40:06.867 回答
7

Phoenix 1.1.0 的引入Phoenix.ConnTest.assert_error_sent/2使测试类似案例更容易。

文档中

断言错误已被包装并以给定状态发送。

对于测试您期望引发错误并将响应包装在 HTTP 状态中的操作很有用,内容通常由您的MyApp.ErrorView.

使用示例:

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

response = assert_error_sent 404, fn ->
  get conn(), "/users/not-found"
end
assert {404, [_h | _t], "Page not found"} = response
于 2016-03-03T20:43:17.600 回答