I’m trying to use a separate router for an API. I’m forwarding the request from the main router to a plug which in turn forwards the request to the correct version router based on the accepts header.
Everything is works except my controller tests. I’m getting a route not found. Here’s my main router:
defmodule MyAppWeb.Router do
use MyAppWeb, :router
forward "/api", MyAppWeb.Plug.API.Version
end
Here’s the plug that forwards the request to the correct router:
defmodule MyAppWeb.Plug.API.Version do
import Plug.Conn
alias MyAppWeb.Routers.API
@versions Application.get_env(:mime, :types)
def init(opts), do: opts
def call(conn, opts) do
[accept] = get_req_header(conn, "accept")
@versions
|> Map.fetch!(accept)
|> call_router(conn, opts)
end
defp call_router([:v2], conn, opts) do
API.V2.Router.call(conn, API.V2.Router.init(opts))
end
defp call_router(_, conn, _opts) do
conn
|> send_resp(404, "Not Found")
|> halt()
end
end
Here’s the api router that eventually receives the request:
defmodule MyAppWeb.Routers.API.V2.Router do
use MyAppWeb, :router
pipeline :api do
plug :accepts, [:v2]
end
scope "/", MyAppWeb.API.V2 do
pipe_through :api
resources "/stores", StoreController, except: [:delete]
end
end
Using post man, everything works as expected. But when I run my tests, I get the following errors:
3) test index lists all stores (MyAppWeb.API.V2.StoreControllerTest)
test/my_app_web/controllers/api/v2/store_controller_test.exs:17
** (Phoenix.Router.NoRouteError) no route found for GET /stores (MyAppWeb.Router)
code: conn = get conn, store_path(conn, :index)
stacktrace:
(my_app) lib/my_app_web/router.ex:1: MyAppWeb.Router.__match_route__/4
(my_app) lib/phoenix/router.ex:303: MyAppWeb.Router.call/2
(my_app) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.plug_builder_call/2
(my_app) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.call/2
(phoenix) lib/phoenix/test/conn_test.ex:224: Phoenix.ConnTest.dispatch/5
test/my_app_web/controllers/api/v2/store_controller_test.exs:18: (test)
When I run my routes (mix phx.routes MyAppWeb.Routers.API.V2.Router
), I get the following:
store_path GET /stores MyAppWeb.API.V2.StoreController :index
Here’s my controller test:
defmodule MyAppWeb.API.V2.StoreControllerTest do
use MyAppWeb.ConnCase
import MyAppWeb.Routers.API.V2.Router.Helpers
setup %{conn: conn} do
{:ok, conn: put_req_header("accept", "application/vnd.app.v2+json")}
end
describe "index" do
test "lists all stores", %{conn: conn} do
conn = get conn, store_path(conn, :index)
assert json_response(conn, 200)["data"] == []
end
end
end
Any ideas where I’m going wrong?