菲尼克斯控制器测试,设置请求主机 [英] Phoenix controller test, set request host
本文介绍了菲尼克斯控制器测试,设置请求主机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在进行多站点应用程序。在测试控制器之前,我想在连接上设置请求主机。在Rails中,我们可以使用
before :each do
request.env["HTTP_REFERER"] = '/'
end
有人能建议如何在凤凰城做同样的事情吗?
编辑1:我可以使用
conn |> put_req_header("host", "abc.com")
,但这不会更改conn
对象中的host
属性。它仍然指向"www.Example.com"
编辑2:我也尝试了
test "creates resource and redirects when data is valid", %{conn: _conn} do
struct_url = %{Myapp.Endpoint.struct_url | host: "abc.com"}
conn = post(conn, registration_url(struct_url, :create, user: @valid_attrs))
assert redirected_to(conn) == "/"
end
但我收到以下错误:
$ mix test test/controllers/registration_controller_test.exs 1) test creates resource and redirects when data is valid (Myapp.RegistrationControllerTest)
test/controllers/registration_controller_test.exs:14
** (RuntimeError) expected action/2 to return a Plug.Conn, all plugs must receive a connection (conn) and return a connection
stacktrace:
(myapp) web/controllers/registration_controller.ex:1: Myapp.RegistrationController.phoenix_controller_pipeline/2
(myapp) lib/phoenix/router.ex:255: Myapp.Router.dispatch/2
(myapp) web/router.ex:1: Myapp.Router.do_call/2
(myapp) lib/myapp/endpoint.ex:1: Myapp.Endpoint.phoenix_pipeline/1
(myapp) lib/phoenix/endpoint/render_errors.ex:34: Myapp.Endpoint.call/2
(phoenix) lib/phoenix/test/conn_test.ex:193: Phoenix.ConnTest.dispatch/5
test/controllers/registration_controller_test.exs:16
REGISTION_CONTROLER.EX第1行defmodule Myapp.RegistrationControllerTest do
编辑3:
创建registration_controller.ex
def create(conn, %{"user" => user_params}) do
user_changeset = User.changeset(%User{}, user_params)
if user_changeset.valid? do
Repo.transaction fn ->
user = Repo.insert!(user_changeset)
user_site = Ecto.Model.build(user, :user_sites, site: site_id(conn))
Repo.insert!(user_site)
conn
|> put_flash(:info, "Your account was created")
|> put_session(:current_user, user)
|> redirect(to: "/")
end
else
conn
|> render("new.html", changeset: user_changeset)
end
end
推荐答案
由于Plug.Conn
是一个结构,如果您需要更改主机,可以使用map update syntax:
conn = %{conn | host: "abc.com"}
如果要更改管道中的密钥,请使用Map.put/3:
conn =
conn()
|> put_header("content-type", "json")
|> Map.put(:host, "abc.com")
如果希望在每次测试之前运行某个程序,可以使用ExUnit.Callbacks.setup/2
setup do
conn = %{conn() | host: "abc.com"}
{:ok, conn}
end
test "foo", %{conn: conn} do
get(conn, ...)
end
编辑
您将看到主机由以下各项确定:
host: uri.host || "www.example.com"
调用
这意味着为了获取所需的主机,您需要在url中指定它,而不是conn
试试:
struct_url = %{MyApp.Endpoint.struct_url | host: "abc.com"}
conn = get(conn, foo_url(struct_url, :index)) #note foo_url not foo_path
编辑2
这里的问题是:
Repo.transaction fn ->
user = Repo.insert!(user_changeset)
user_site = Ecto.Model.build(user, :user_sites, site: site_id(conn))
Repo.insert!(user_site)
conn
|> put_flash(:info, "Your account was created")
|> put_session(:current_user, user)
|> redirect(to: "/")
end
错误告诉您action/2
应该返回Plug.Conn
,而您返回的是transaction/3的结果(将是{:ok, value}
或{error, value}
这意味着您的函数将返回{:ok, conn}
尝试:
Repo.transaction fn ->
user = Repo.insert!(user_changeset)
user_site = Ecto.Model.build(user, :user_sites, site: site_id(conn))
Repo.insert!(user_site)
end
conn
|> put_flash(:info, "Your account was created")
|> put_session(:current_user, user)
|> redirect(to: "/")
如果您希望根据事务返回不同的结果,那么我会将整个部分移到类似AccountService.create
的模块函数中,然后使用类似以下的CASE语句:
def create(conn, %{"user" => user_params}) do
case MessageService.create(user_params) do
{:ok, user} ->
|> put_flash(:info, "Your account was created")
|> put_session(:current_user, user)
|> redirect(to: "/")
{:error, changeset} ->
conn
|> render("new.html", changeset: user_changeset)
end
end
这篇关于菲尼克斯控制器测试,设置请求主机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文