在集成测试中访问会话

时间:2017-06-09 15:04:35

标签: ruby-on-rails ruby testing integration-testing railstutorial.org

我是Rails初学者,正在通过Michael Hartl的Rails教程工作,我收到一个错误,我不知道如何解决。作为参考,这是为了实现清单9.24(https://www.railstutorial.org/book/advanced_login)中的更改。

我跳过了第9章(因为它应该是可选的)但是在第10章中它要求包括列表9.24中所做的更改,所以我做了,我的测试仍然失败。

这是我在运行rails test时收到的错误

Error:
UsersEditTest#test_unsuccessful_edit:
NoMethodError: undefined method `session' for nil:NilClass
    test/test_helper.rb:18:in `log_in_as'
    test/integration/users_edit_test.rb:14:in `block in <class:UsersEditTest>'


bin/rails test test/integration/users_edit_test.rb:12

E

Error:
UsersEditTest#test_successful_edit:
NoMethodError: undefined method `session' for nil:NilClass
    test/test_helper.rb:18:in `log_in_as'
    test/integration/users_edit_test.rb:28:in `block in <class:UsersEditTest>'

失败的测试(在test / integration / users_edit_test.rb中)是:

test "successful edit" do
    log_in_as(@user)
    get edit_user_path(@user)
... end
test "unsuccessful edit" do
     log_in_as(@user)
    get edit_user_path(@user)
... end

这里是正在调用的集成/ test_helper方法

# Log in as a particular user.
  def log_in_as(user)
    session[:user_id] = user.id
  end

特别令人困惑的是,测试助手中还有另一种方法也使用会话,并在user_login_test中调用,该方法工作正常。

非常感谢任何帮助!!

3 个答案:

答案 0 :(得分:3)

会话仅在测试用例中的第一个请求后才可用。您的log_in_as(user)帮助程序方法可以启动实际记录用户的请求,以便会话将填充user.id

查看此主题中的讨论:

https://github.com/rails/rails/issues/23386#issuecomment-192954569

答案 1 :(得分:3)

为了将来遇到此问题的任何人的利益,对于集成测试,您需要定义一个test_helper方法,该方法会发布到会话控制器创建方法,而不是特别修改会话,例如。

class ActionDispatch::IntegrationTest
    def log_in_as(user, password: 'password')
        post login_path, params: { session: { email: user.email, password: password} }
    end
end

你的其他会话方法工作的原因是因为它没有为会话哈希分配任何东西,只是检查一个值是否存在。对于集成测试,您无法直接使用permanentnce修改会话哈希。

答案 2 :(得分:0)

这就是我为 Rails 6 所做的:

test_helper.rb 添加了一个助手:

# test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require_relative "../config/environment"
require "rails/test_help"

class ActiveSupport::TestCase
  # Run tests in parallel with specified workers
  parallelize(workers: :number_of_processors)

  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...
  def sign_in_as(user, password)
    post sessions_url, params: { email: user.email, password: password }
  end
end

以下是 users_controller_test.rb 中的测试示例:

test "should show user" do
  sign_in_as(@user, 'password')

  get user_url(@user)
  assert_response :success
end

根据表单的结构,您可能需要将凭据封装在 :sessions 哈希中。检查当您的表单在页面上呈现时,名称属性中是否有 session[email]

<input type="text" name="session[email]" id="email">

如果是这种情况,请更改 sign_in_as 方法以在 :params 中说明这一点:

def sign_in_as(user, password)
  post sessions_url, params: { session: { email: user.email, password: password } }
end