**(Plug.Conn.AlreadySentError)响应已发送

时间:2016-09-07 22:46:42

标签: elixir phoenix-framework ex-unit

我一直在研究this question with an almost identical challenge(和答案)

- 除了我的技术非常低,我对自己缺乏洞察力感到非常尴尬<:/

系统

macOS 10.11.6

$ mix -v
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:8:8] [async-threads:10][hipe] [kernel-poll:false] [dtrace]

Mix 1.3.2

微量

$ mix test
...

  1) test /api/v1/blogs#index returns a list of blogs (ScoutServer.BlogControllerTest)
     test/controllers/blog_controller_test.exs:5
     ** (Plug.Conn.AlreadySentError) the response was already sent
     stacktrace:
       (plug) lib/plug/conn.ex:459: Plug.Conn.resp/3
       (plug) lib/plug/conn.ex:446: Plug.Conn.send_resp/3
       (scout_server) web/controllers/blog_controller.ex:1: ScoutServer.BlogController.action/2
       (scout_server) web/controllers/blog_controller.ex:1: ScoutServer.BlogController.phoenix_controller_pipeline/2
       (scout_server) lib/scout_server/endpoint.ex:1: ScoutServer.Endpoint.instrument/4
       (scout_server) lib/phoenix/router.ex:261: ScoutServer.Router.dispatch/2
       (scout_server) web/router.ex:1: ScoutServer.Router.do_call/2
       (scout_server) lib/scout_server/endpoint.ex:1: ScoutServer.Endpoint.phoenix_pipeline/1
       (scout_server) lib/scout_server/endpoint.ex:1: ScoutServer.Endpoint.call/2
       test/controllers/blog_controller_test.exs:17: (test)

.

Finished in 0.1 seconds
5 tests, 1 failure

Randomized with seed 210569

网/ router.ex

pipeline :api do
  plug :accepts, ["json"]
end

scope "/api/v1", ScoutServer do
  pipe_through :api
  resources "/blogs", BlogController
end

测试/ test_helper.exs

# Add this above `ExUnit.start`
defmodule ScoutServer.Case do
  use ExUnit.CaseTemplate
  alias ScoutServer.Repo

  setup do
    # Explicitly get a connection before each test
    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo)
  end

  using do
    quote do
      alias ScoutServer.Repo
      use Plug.Test

      # Remember to change this from `defp` to `def` or it can't be used in your
      # tests.
      def send_request(conn) do
        conn
        |> put_private(:plug_skip_csrf_protection, true)
        |> ScoutServer.Endpoint.call([])
      end

    end
  end
end

ExUnit.start

Ecto.Adapters.SQL.Sandbox.mode(ScoutServer.Repo, :manual)

测试/控制器/ blog_controller_test.exs

defmodule ScoutServer.BlogControllerTest do
  use ScoutServer.Case, async: false
  alias ScoutServer.Blog

  test "/api/v1/blogs#index returns a list of blogs" do
    blogs =
      %Blog{title: "scout", content: "scouting"}
      |> Repo.insert
      |> List.wrap
    blogs_as_json = Repo.all(Blog)
      |> Poison.encode!(blogs)

    # conn = get conn, "/api/v1/blogs"
    # assert html_response(conn, 200) =~ blogs_as_json

    response = conn(:get, "/api/v1/blogs", blogs_as_json)
      |> send_request

    assert response.status == 200
    assert response.resp_body == blogs_as_json
  end

end

1 个答案:

答案 0 :(得分:3)

我被blog_controller_test.ex所吸引,以至于我完全忘记了真实的东西:(

defmodule ScoutServer.BlogController do
  use   ScoutServer.Web, :controller
  alias ScoutServer.Blog

  # plug :action - not sure why, but without the comment the test fails!

  def index(conn, _params) do
    blogs = Repo.all(Blog)
    render conn, blogs: blogs
  end
end

但幸运的是Pawel Duda把我从'消费'中撕掉了 - 那就是Pawel!

实际上 - 插件:动作事物已成为过去,因为this issue文件;这又证明了time / space依赖于网络的真实情况:)