在 current_user 上调用名称方法导致测试错误(ruby 在 rails 上)

Calling name method on current_user causes testing error (ruby on rails)

我完成了 Michael Hartl 的 Rails 教程的第 11 章,之后我开始寻找使用 thumbs_up gem 为微博添加一些声誉和投票功能的方法。

我想在导航栏的小方框(如 Stack Overflow)中显示当前用户的声誉。我可以使用以下方法获得用户名和信誉以正常显示:

       <li class="rep_box"><%= current_user.name %> <%= current_user.karma %> </li>

该页面工作正常并正确呈现用户名和声誉,但现在我遇到了几个错误并失败了。如果我删除上面的代码行,一切都会再次正常工作。

这是错误的一个例子——它们几乎都是一样的:

>ERROR["test_should_get_home", StaticPagesControllerTest, 2016-04-09 04:36:31 -0400]
 test_should_get_home#StaticPagesControllerTest (1460190991.59s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `name' for nil:NilClass
            app/views/layouts/_header.erb:6:in `_app_views_layouts__header_erb__1475229759153232172_2241208160'
            app/views/layouts/application.html.erb:12:in `_app_views_layouts_application_html_erb__4357373253304461109_2216429940'
            test/controllers/static_pages_controller_test.rb:9:in `block in <class:StaticPagesControllerTest>'
        app/views/layouts/_header.erb:6:in `_app_views_layouts__header_erb__1475229759153232172_2241208160'
        app/views/layouts/application.html.erb:12:in `_app_views_layouts_application_html_erb__4357373253304461109_2216429940'
        test/controllers/static_pages_controller_test.rb:9:in `block in <class:StaticPagesControllerTest>'
undefined method `name' for nil:NilClass

这意味着 current_user 在调用 name 时是 nil。确保此时已正确分配,错误就会消失。

你需要sign_in一个用户才有current_user.

你可以这样做:

let(:curr_user) { User.create(...attrs...) }
sign_in curr_user

来自Devise documentation:

Devise includes some test helpers for functional specs. In order to use them, you need to include Devise in your functional tests by adding the following to the bottom of your test/test_helper.rb file (make sure you place it out of scope of ActiveSupport::TestCase which is the default class inside of test/test_helper.rb):

class ActionController::TestCase   
   include Devise::TestHelpers 
end

Just be sure that this inclusion is made after the require 'rspec/rails' directive.

Now you are ready to use the sign_in and sign_out methods. Such methods have the same signature as in controllers:

sign_in :user, @user   # sign_in(scope, resource) 
sign_in @user          # sign_in(resource)

sign_out :user         # sign_out(scope) 
sign_out @user         # sign_out(resource)

否则,current_user 将正确地变为 nil。如果你想让你的代码容忍这个,那么你应该在视图中用 unless current_user.nil? 之类的东西来保护那个位。我还看到有人创建了一个 current_user_or_guest 方法来代替他们对 current_user.

的使用

在助手中,他们创建了这样的东西:

  def current_or_guest_user
    if current_user
      current_user
    else
      User.new
    end
  end

编辑:

Michael Hartl's Rails tutorial 中,它不使用 Devise,而是让您创建一个 current_user 方法,如下所示:

def current_user
  User.find_by(id: session[:user_id])
end

当没有session[:user_id]时,这个current_user方法会returnnil。在 current_user 不再 return nil 之前,您仍然需要对用户进行身份验证。 test/integration/users_login_test.rb.

中已有测试用户认证测试的代码

因此,在您的测试中,您需要确保执行类似 log_in User.find_by(id: <some valid ID>) 的操作来验证用户身份。这将确保 current_user 像在正常使用上下文中一样执行。

您可以添加一个 test/support 目录,并在该目录中创建 login_helpers.rb

def log_in_with(email,password) do
  get login_path
  post login_path, session: { email: email, password: password }
end

然后,为确保这些方法可用,在您的 test/test_helper.rb 中添加:

Dir[Rails.root.join('test/support/**/*.rb')].each { |f| require f }

现在,在需要经过身份验证的用户的测试中,执行:

log_in_with('a_valid_email', 'its valid password')