Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign uprails5 can't access session in ActionDispatch::IntegrationTest #23386
Comments
rubys
changed the title
rails5 can't assess session in ActionDispatch::IntegrationTest
rails5 can't access session in ActionDispatch::IntegrationTest
Jan 31, 2016
maclover7
added
the
actionpack
label
Jan 31, 2016
This comment has been minimized.
This comment has been minimized.
The session is an internal structure for the controller. Integration test is more black box than controller tests were. I don't think we should be testing internals of the controller like this. I would rework the test to test something visible in the UI instead. |
dhh
closed this
Feb 1, 2016
This comment has been minimized.
This comment has been minimized.
I fully understand removing access to low level details. But in this case, that just exposes what is the real problem here: http://api.rubyonrails.org/classes/ActionDispatch/Integration/RequestHelpers.html is woefully deficient. Don't get me wrong, it is fine if you are testing a single controller action in isolation. But once you want to test anything that involves session logic in your controller, you end up needing things like this: https://github.com/jnicklas/capybara#clicking-links-and-buttons and https://github.com/jnicklas/capybara#interacting-with-forms. I don't think that these methods would be hard to write (Rails already has access to response.body and css_selector logic). I don't think they could make the current Rails 5 schedule. I don't think that access to a session should be removed until the higher level functions are in place. Looking at the problem I'm seeing, it appears that the issue is that the session isn't created yet. Doing an unrelated action (like a get) would create a session. |
This comment has been minimized.
This comment has been minimized.
We tested all of Basecamp 3 with controller tests driven by ActionDispatch::IntegrationTest, and I didn't find a need for capybara-style button clickers etc. I think it'd be nice to offer this as an additional level-up, but it's not a blocker in my book. If that's something you'd like to take a swing at, please do! Would make a great addition to Rails 5.1. |
This comment has been minimized.
This comment has been minimized.
cannikin
commented
Mar 5, 2016
@dhh Can you explain your technique for this? Do you actually test "should get new" do
user = users(:john)
post login_url, params: { email: user.email, password: user.password }
get new_post_url
assert_response :success
end Sorry to bug you but I haven't found any docs in the wider world that explain this new recommended controller testing paradigm. |
This comment has been minimized.
This comment has been minimized.
That's exactly it. We've wrapped that into a helper method that we usually then use in the setup of a controller. So: # helper method
def sign_in_as(name)
post login_url, params: { sig: users(name).perishable_signature )
end
class SomeControllerTest
setup { sign_in_as 'david' }
test 'the truth' do
.. |
This comment has been minimized.
This comment has been minimized.
cannikin
commented
Mar 7, 2016
Thank you sir! I'm liking the feel of these new controller-integration hybrid tests so far. |
cannikin
referenced this issue
Mar 21, 2016
Closed
Authlogic::TestCase no longer works in Rails 5 controller tests #489
This comment has been minimized.
This comment has been minimized.
nikolaokonesh
commented
Jun 15, 2016
@dhh Hi |
This comment has been minimized.
This comment has been minimized.
If you still need this (I did def session_header(session)
session = session.reverse_merge(session_id: SecureRandom.hex)
key_generator = ActiveSupport::KeyGenerator.new(ENV.fetch('SECRET_KEY_BASE'), iterations: 1000)
secret = key_generator.generate_key('encrypted cookie')
sign_secret = key_generator.generate_key('signed encrypted cookie')
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: 'SHA1', serializer: ActiveSupport::MessageEncryptor::NullSerializer)
{ 'Cookie' => "_your_app_session=#{encryptor.encrypt_and_sign(session.to_json)}" }
end You can use it like so: get '/needs/session', headers: session_header('some' => 'data') This works with the current 5.0 versions, but can break any time for newer versions. Use at your own risk! The better way would be to follow @dhh's advise:
|
This comment has been minimized.
This comment has been minimized.
evgenyfadeev
commented
Apr 23, 2017
•
When authentication depends on an external service, sometimes it might not be available for proper integration tests; for instance, it might be behind some firewall. Therefore - one has to either stub the authentication service or create a fake test login controller. The second will need to assess the session and that would run contrary to the idea that session is not available for the purposes of running integration tests. Stubbing the service is also extra work. Perhaps adding an official login method, available from the test cases and not giving full access to session would be a good compromise. Otherwise, we just have an extra stumbling block in the way of testing. |
added a commit
to cflipse/loudoun_codes
that referenced
this issue
May 20, 2017
added a commit
to cflipse/loudoun_codes
that referenced
this issue
May 21, 2017
islemaster
referenced this issue
May 21, 2018
Merged
Tech Debt: Clean up RegistrationsController tests #22556
This comment has been minimized.
This comment has been minimized.
2 years later, and my custom code above bit me when upgrading to 5.2. But thankfully I can now use the technique suggested by @dhh. So, thx again man! |
rubys commentedJan 31, 2016
Reproduction scenario:
Test results: throwaway.txt
[this is with rails master]
Note: I reran rails test with BACKTRACE set as the actual error is inside action_dispatch/testing/test_process.
Example with similar code working in Rails 4.2:
Code: http://intertwingly.net/projects/AWDwR4/checkdepot-215-42/section-10.4.html#cmd3
Test: http://intertwingly.net/projects/AWDwR4/checkdepot-215-42/section-10.4.html#cmd8
Results for same example in Rails 5 (master):
http://intertwingly.net/projects/AWDwR4/checkdepot/section-10.4.html#cmd8