Having a View, with a function using the Routes.*_url helper, everything works fine, until I try to test this function directly.
defmodule ExampleWeb.PageView do
use ExampleWeb, :view
def url_helper(conn, slug) do
Routes.page_url(conn, :show, slug)
end
end
defmodule ExampleWeb.PageViewTest do
use ExampleWeb.ConnCase, async: true
alias ExampleWeb.PageView
test "url_helper/2", %{conn: conn} do
slug = "my-example"
assert PageView.url_helper(conn, slug) == "http://localhost:4002/my-example"
end
end
I’m at home now and therefore have a bit more time to actually take a look
The conn in oyur tests is a connectiont that is created from thin air and has no associated endpoint. Though the endpoint is required for the URL helpers to actually create the URL.
You can use Phoenix.ConnTest.bypass_through/x (IIRC) to make that stub connection a “full” one with the sideeffect of it passing through the full pipeline stack, which might make the test require a significant amount more time.
To be honest, I don’t really understand, why you need to test the URL helpers. That is basically testing if the path helpers do their job while tightly coupling test results to certain config values…
I just trimmed this down to have a somewhat minimal example here. In my real app I’m of course not only having the URL helper in there, I have a function that uses them to create an RSS feed. I wanted to generate this in the view, so I have a nice and clean controller like:
def index(conn, _params) do
posts = Blog.list_posts()
conn
|> put_resp_header("content-type", "application/rss+xml")
|> render("index.rss", posts: posts)
end
in my View I then have a little function that turns a Post into an Item for rendering the xml and I need the full urls for that.
I don’t want to unit-test Phoenix or the url helper itself. I just want to test a function in one of my views that happens to use one of those helpers, because I need absolute urls in there.
The conn you get from MyApp.ConnTest is not linked to any particular endpoint. You could have multiples of those in your project. Therefore you need to link that conn (basically a plain request) to an endpoint before you can use it to unit test things depending on a conn for a specific endpoint. Without that linkage the url generation doesn’t know which host to use, which path was requested, if the endpoint was mounted to a subfolder, …
For most ConnTests those things are set when you do get conn, path, …. but for unit tests you need to handle it on your own.