Why does :accepts plug not 406 when Accept header is missing? How to test controller?

At work, we are trying to use plug :accepts, ["json-api"] with a custom mime type and are running into some issues and questions. To help illustrate I’ve created a basic Phoenix Application with some tests on GitHub.

My first question: Why does a request that lacks an Accept header return 200 when it is piped through plug :accepts, ["json-api"]? I would expect the request to 406 given that it does not meet the specification of the accept header requirement. I’ve looked at the Phoenix.Controller source code and, if I’m reading it correctly, if the Accept header is missing, Phoenix adds the first binary in the accepts list as the format. Does anyone know why that’s the expected behavior?

Consider this failing test as an example:

defmodule Accepts.V1.FooControllerTest do
  use Accepts.ConnCase, async: true

  test "406 without accept header", %{conn: conn} do
    assert_raise Phoenix.NotAcceptableError, fn ->
      get(conn, foo_path(conn, :index, %{greet: "world"}))
    end
  end
end

My second question: Why do requests with incorrect headers raise an exception during tests but render an error view in prod and dev (when debug_errors is false)?

Consider this passing test as example:

defmodule Accepts.V1.FooControllerTest do
  use Accepts.ConnCase, async: true

  @acceptable_json_api_header "application/vnd.api+json"
  @unacceptable_json_api_header "application/json"

  test "406 with unacceptable json-api header", %{conn: conn} do
    assert_raise Phoenix.NotAcceptableError, fn ->
      conn
      |> put_req_header("accept", @unacceptable_json_api_header)
      |> get(foo_path(conn, :index, %{"greet" => "world"}))
    end
  end
end

I would prefer to write the test as something like:

test "406 with unacceptable json-api header", %{conn: conn} do
  conn =
    conn
    |> put_req_header("accept", @unacceptable_json_api_header)
    |> get(foo_path(conn, :index, %{"greet" => "world"}))

  assert json_response(conn, 406)
end

Is there a way to have the tests render the response rather than raise the exception? I’ve tried setting debug_errors: true in config/test.exs without effect.

Thanks for any help!

After posting this question, I think I want to disregard my first question. The Accept header is an indication of what the client is able to understand in the response. If the client fails to indicate what it accepts, the Phoenix behavior is to regard that lack of indication as an implicit declaration that it accepts anything. Sorry for the premature question.

If anyone has insight into rendering the 406 during tests, that would be great.