chensan
I’m writing tests for my controller:
defp log_in_user(%{conn: conn, log_in_as: email}) do
role = role_fixture()
user = user_fixture(role, email: email)
conn = assign(conn, :current_user, user)
{:ok, conn: conn, user: user}
end
defp create_site(%{conn: conn, user: user}) do
site = site_fixture(user)
{:ok, site: site}
end
describe "delete site" do
setup [:log_in_user, :create_site]
@tag log_in_as: "sam"
test "deletes chosen site", %{conn: conn, site: site} do
conn = delete(conn, Routes.site_path(conn, :delete, site))
assert redirected_to(conn) == Routes.site_path(conn, :index)
assert_error_sent 404, fn ->
get(conn, Routes.site_path(conn, :show, site))
end
end
end
The weird thing here is conn.assigns.current_user becomes nil in assert_error_sent where it should have value.
I found some similar questions around the web:
- Troubleshooting a failed test 302 redirect instead of 200 - #3 by chensan
- https://stackoverflow.com/questions/50110449/phoenix-controller-test-case-loses-current-user
- https://stackoverflow.com/questions/46363292/losing-conn-assigns-in-the-middle-of-a-test
Seems the problem is caused by Phoenix.ConnTest – Phoenix v1.4.0, and there’s a fix:
saved_assigns = conn.assigns
conn =
conn
|> recycle()
|> Map.put(:assigns, saved_assigns)
I don’t quite understand why, it’s so unexpected in our tests. Anyone could help explain it?
Trending in Questions
Hello!
Suppose you are building workflow (order / task / payment) processing system with the following requirements:
Each workflow con...
New
I’m aware of 2 such projects, are there others?
git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
Hi all,
I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
Hi everyone.
My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
Hi,
we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley:
Mutonex gamedesign was finish...
New
Hello
I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New
Other Trending Topics
Hey there,
I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first.
...
New
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly)
AI dream has many faces, but general...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #ai
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #blog-post
- #ecto-query
- #elixirconf-us
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #security
- #hex










Showing Posts 1 to 8- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
LostKobrakai
recycledoes essentially what happens if you start a new request in the browser. Any new request in the browser will start of without any assigns. Usually you’re kept logged in by putting something in the session for the user.chensan
When I logged in a website, I would expect myself logged-in all the time until I log out. But Phoenix recycling breaks this expectation.
LostKobrakai
That’s just not true. If you’re not using session based authentication you’d need to log in new for each request. The only data which survives between requests is the stuff you put into the session. Anything else is discarded at the end of a request. That’s true for the request you do with a browser in dev mode and exactly what recycle mimics for tests.
chensan
Ok, so how can I make the tests better? Writing
conn = conn |> cycle() |> Map.put(:assigns, conn.assigns)everywhere in my controller tests is so ugly.idi527
Maybe Plug.Test — Plug v1.20.2
I wouldn’t change assigns manually, instead I’d pipe the requests through the actual plug pipelines with the session set via
Plug.Test.init_test_session/2to get the expectedconnwith all relevant assigns set.LostKobrakai
Either what @idi527 said: Use the session and your real plugs / pipelines.
Or simply not reuse the conn for places where you’re e.g. testing a single plug.
chensan
Can we say the tip presented in Programming Phoenix book for easier testing is defective
In the beginning I just logged in user with naive
post(conn, Routes.session_path(conn, :create), ...):No need to call
recycle()in this code.chensan
After reading the source code, I’d like to share what I learned so far.
When we run
get(conn, Routes.site_path(conn, :show, site)), a newconnwas created, and cookies and some request headers (~w(accept authorization)) from oldconnare copied to newconn- that’s what Phoenix recycling does for us, it emulates the behavior of browser. Butconn.assignsis not copied, results in anilvalue ofcurrent_user.The reason
post(conn, Routes.session_path(conn, :create), session: %{email: user.email, password: "123456"} )works is becauseAuthmodule selects another path:Thanks all for your kind help