Like many rails developers, I’ve been dabbling with elixir and the phoenix framework. While phoenix is clearly a lot like rails, it’s always an adjustment to learn a new framework and it is certainly an adjustment for me to get used to the functional programming paradigm coming from ruby.
One major philosophical difference between elixir and ruby is the attitude towards mocks and stubs. As elixir creator José Valim said:
I will fight against mocks, stubs and YAML in Elixir with all my… friendliness and energy to promote proper education on those topics.
This was a struggle for me since I was used to stubbing the
current_user method in my rails controller tests to fake a user being logged in. I initially did
Plug.Conn.put_session(:user_id, id) to store a user’s id in the session. This worked great, but was hard to use in tests because you can’t do
put_session on a connection in controller tests without first making a request in the test. This slows things down for no real benefit.
I found this extremely helpful post that explains a ways to assign the current user to the connection directly in order to make testing easier. It doesn’t actually explain how to do this in the production code, though, since just assigning a current user to the connection doesn’t actually persist it to the session so the user won’t be logged in on subsequent requests. After some thinking I came up with a solution so I thought I’d write it down here to hopefully help myself in the future and other people learning elixir and/or phoenix.
I have a module that handles session stuff called
What I’m doing here is storing the current user’s id in the session as well as assigning the user to the connection. When calling the
current_user function if the connection does not already have a
current_user assigned, I look up the user from the id stored in the session and assign that user to the session. This means that multiple calls to
current_user won’t do a database lookup, but will just find it already assigned to the connection.
I added the following code to the
test/support/conn_case.ex file inside the
quote do block:
This allows me to write tests assuming a user is logged in that start like:
I hope this helps you write phoenix apps with less onerous test setup! If you have better solutions please let me know in the comments.