nil的未定义方法:RSpec中的NilClass,即使手动测试通过

时间:2016-01-30 02:24:22

标签: ruby rspec capybara padrino

我收到一个非常奇怪的错误,因为它在浏览器中完全正常工作,即显示帖子并显示作者的姓名。没有错误。

然而,功能测试正在打破,我不明白为什么。这很奇怪。

posts_features_spec.rb:

require 'spec_helper'
require_relative '../support/spec_helper_methods'

feature "Post Features" do
  include SpecHelperMethods
  let(:user){ User.create(name: "Andy", email: "user@email.com", password: "password", password_confirmation: "password") }

  describe "Creating Posts" do
    it "Can create a post" do
      visit '/'
      click_on "Sign Up"
      fill_in 'user[name]', with: "Bob"
      fill_in 'user[email]', with: "bob@email.com"
      fill_in 'user[password]', with: "password"
      fill_in 'user[password_confirmation]', with: "password"
      click_on 'Sign Up'
      click_on 'Login'
      fill_in 'email', with: "bob@email.com"
      fill_in 'password', with: "password"
      click_on 'Login'
      expect(page).to have_content "Successfully signed in!"
      click_on "Create Post"
      fill_in 'post[title]', with: "Title99"
      fill_in 'post[body]', with: "Body99"
      click_on "Post"
      expect(current_path).to eq '/posts'
      expect(page).to have_content "Title99"
      expect(page).to have_content "Body99"
      expect(page).to have_content "Bob"
      expect(page).to have_content "Post Posted!"
    end
  end

  describe 'Post Show page' do
    let(:post){ Post.create title: 'Lazy-loaded Post', body: 'Body', user: user }
    before(:each){ visit "/posts/show/#{post.id}" }

    it "Post's title, body, and author are displayed" do
      expect(page).to have_content "#{post.title}"
      expect(page).to have_content "#{post.body}"
      expect(page).to have_content "#{post.user.name}"
    end
  end
end

控制器:

PadrinoBlog::App.controllers :posts do

  get :new do
    @post = Post.new
    render 'posts/new'
  end

  post :create do
    post = Post.new(params[:post])
    post.user = current_user
    if post.save
      puts Post.all.count
      puts Post.last.inspect
      redirect('/posts', notice: "Post Posted!")
    end
  end

  get :index do
    @posts = Post.order('created_at DESC').all
    render 'posts/index'
  end

  get :show, with: :id do
    @post = Post.find_by_id(params[:id])
    render 'posts/show'
  end

end

index.html.erb:

<%= link_to "Sign Up", 'users/new' %>

<% unless signed_in? %>
  <%= link_to "Login", 'sessions/new' %>
<% end %>

<% if signed_in? %>
  <%= link_to "Logout", 'sessions/destroy' %>
<% end %>

<% if flash[:notice] %>
  <p><%= flash[:notice] %></p>
<% end %>

<% if signed_in? %>
  <%= link_to "Create Post", 'posts/new' %>
<% end %>

<% if @posts %>
  <%= partial 'posts/post', collection: @posts %>
<% end %>

_posts.html.erb:

<div class='post'>
  <h4><%= post.title %></h4>
  <p><%= post.body %></p>
  <p><%= post.user.name %></p>
</div>

运行测试时,显示页面&#39;测试通过,但第一个(长一个)在点击“创建帖子”时中断,用此:

Failure/Error: <p><%= post.user.name %></p>

     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./app/views/posts/_post.html.erb:4:in `block in singleton class'
     # ./app/views/posts/_post.html.erb:-7:in `instance_eval'
     # ./app/views/posts/_post.html.erb:-7:in `singleton class'
     # ./app/views/posts/_post.html.erb:-9:in `__tilt_5665000'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:170:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:170:in `evaluate'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:103:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino/rendering/erb_template.rb:18:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:822:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino/rendering.rb:212:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino-helpers/render_helpers.rb:55:in `block in partial'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:132:in `each'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:132:in `each_with_object'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:132:in `public_send'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:132:in `method_missing'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:99:in `method_missing'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino-helpers/render_helpers.rb:48:in `partial'
     # ./app/views/posts/index.html.erb:20:in `block in singleton class'
     # ./app/views/posts/index.html.erb:-6:in `instance_eval'
     # ./app/views/posts/index.html.erb:-6:in `singleton class'
     # ./app/views/posts/index.html.erb:-8:in `__tilt_5665000'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:170:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:170:in `evaluate'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:103:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino/rendering/erb_template.rb:18:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:822:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino/rendering.rb:212:in `render'
     # ./app/controllers/posts.rb:20:in `block (2 levels) in <top (required)>'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:517:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:517:in `block in route'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:992:in `block in invoke_route'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:987:in `catch'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:987:in `invoke_route'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:952:in `block in route!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:53:in `block in call_by_request'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:84:in `block in rotation'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:83:in `loop'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:83:in `with_object'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:83:in `rotation'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:49:in `call_by_request'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router.rb:43:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:949:in `route!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:932:in `block in dispatch!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `block in invoke'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `catch'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `invoke'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:930:in `dispatch!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:906:in `block in call!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `block in invoke'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `catch'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `invoke'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:906:in `call!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rspec-padrino-0.2.2/lib/rspec/padrino/initializers/last_application.rb:12:in `block (2 levels) in <top (required)>'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:894:in `call'
     # ./lib/connection_pool_management_middleware.rb:7:in `block in call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/abstract/connection_pool.rb:292:in `with_connection'
     # ./lib/connection_pool_management_middleware.rb:7:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sass-3.4.21/lib/sass/plugin/rack.rb:54:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/xss_header.rb:18:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/json_csrf.rb:18:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/frame_options.rb:31:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-1.6.4/lib/rack/head.rb:13:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-1.6.4/lib/rack/methodoverride.rb:22:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:225:in `context'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:220:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:2021:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1486:in `block in call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1795:in `synchronize'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1486:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/router.rb:84:in `block in call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/router.rb:75:in `each'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/router.rb:75:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-test-0.6.3/lib/rack/mock_session.rb:30:in `request'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rspec-padrino-0.2.2/lib/rspec/padrino/initializers/last_application.rb:34:in `block (2 levels) in <top (required)>'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-test-0.6.3/lib/rack/test.rb:244:in `process_request'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-test-0.6.3/lib/rack/test.rb:58:in `get'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:60:in `process'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:38:in `block in process_and_follow_redirects'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:37:in `times'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:37:in `process_and_follow_redirects'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:26:in `submit'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/form.rb:77:in `submit'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/node.rb:61:in `click'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/node/element.rb:134:in `block in click'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/node/base.rb:84:in `synchronize'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/node/element.rb:134:in `click'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/node/actions.rb:13:in `click_link_or_button'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/session.rb:686:in `block (2 levels) in <class:Session>'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
     # ./spec/features/posts_features_spec.rb:25:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:17:in `block (2 levels) in <top (required)>'

就像我说的那样,没有问题在浏览器中本地运行,没有任何问题,但是这个测试会中断,这真的很奇怪,特别是因为show view(不会中断)是:

<h4><%= @post.title %></h4>
<p><%= @post.body %></p>
<p><%= @post.user.name %></p>

我甚至尝试在索引视图中没有部分内容的情况下执行:

<% @posts.each do |post| %>
  <h4><%= post.title %></h4>
  <p><%= post.body %></p>
  <p><%= post.user.name %></p>
<% end %>

...但我得到完全相同的错误。 Wtf还在继续?

我已将此状态推送到提交here

1 个答案:

答案 0 :(得分:1)

检查您的代码并运行测试我没有收到错误,因此我快速查看了您的迁移,最后一次迁移将用户添加到帖子中。我猜你在测试环境中遇到了DB问题

padrino rake ar:migrate:reset -e test

应该重置数据库并解决问题