2

I've been studying this question with an almost identical challenge (and the answers )

- except mine is so incredibly low tech that I'm totally embarrassed at my own lack of insight <:/

System

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

Trace

$ 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

web/router.ex

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

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

test/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)

test/controllers/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
Community
  • 1
  • 1
walt_die
  • 580
  • 5
  • 20

1 Answers1

4

I was so consumed by the blog_controller_test.ex that I totally forgot about the real thing :(

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

But luckily Pawel Duda tore me out of my 'consumption' - thx Pawel!

Actually - the plug :action thing is a thing of the past, as this issue documents; which, again, proves how time/space dependent the web really is :)

walt_die
  • 580
  • 5
  • 20