Pra*_*oya 5 elixir elixir-framework phoenix-framework
我正在制作一个多站点应用程序.我想在测试控制器之前在连接上设置请求主机.在Rails中我们可以使用
before :each do
request.env["HTTP_REFERER"] = '/'
end
Run Code Online (Sandbox Code Playgroud)
有人可以建议如何在凤凰城做同样的事情吗?
编辑1:我可以使用设置主机
conn |> put_req_header("host", "abc.com"),但这不会更改对象host中的conn属性.它仍然指向"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
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
$ 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
Run Code Online (Sandbox Code Playgroud)
registration_controller.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
Run Code Online (Sandbox Code Playgroud)
由于Plug.Conn是结构,如果需要更改主机,可以使用地图更新语法:
conn = %{conn | host: "abc.com"}
Run Code Online (Sandbox Code Playgroud)
如果要更改管道中的键,请使用Map.put/3:
conn =
conn()
|> put_header("content-type", "json")
|> Map.put(:host, "abc.com")
Run Code Online (Sandbox Code Playgroud)
如果您希望在每次测试之前运行某些东西,可以使用ExUnit.Callbacks.setup/2
setup do
conn = %{conn() | host: "abc.com"}
{:ok, conn}
end
test "foo", %{conn: conn} do
get(conn, ...)
end
Run Code Online (Sandbox Code Playgroud)
编辑
您将看到主机由以下因素决定:
host: uri.host || "www.example.com"
Run Code Online (Sandbox Code Playgroud)
这意味着,为了获得所需的主机,您需要在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
Run Code Online (Sandbox Code Playgroud)
EDIT2
这里的问题是:
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
Run Code Online (Sandbox Code Playgroud)
错误告诉你action/2应该返回一个Plug.Conn但是你要返回事务/ 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: "/")
Run Code Online (Sandbox Code Playgroud)
如果你想根据事务返回不同的结果,那么我会将整个部分移动到类似的模块函数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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2586 次 |
| 最近记录: |