2017-04-03 24 views
0

私はActionView::Template::Error: undefined method [] for nil:NilClassがよくあるエラーだと知っていますが、私の問題に答えるものはありません。私はログインし、新しいプロジェクトページに行き、フォームに記入して新しいプロジェクトを作成する、非常に簡単なテストを持っています。しかし、ログインしてレールがロードされると、Rspec/Capybaraのダッシュボードはページを正しく読み取れず、フォームをテストする前にページが失敗します。Rspec&Capybara:ActionView :: Template :: Error:未定義メソッド `'for nil:NilClass

Rspec/Capybaraは、ログインページのデバイスフォームに問題はありませんが、どのクラスプロジェクトを認識していないようで、そのNilClassを考えると思われません。

ここでspecファイルされる:

require 'rails_helper' 

describe "Creating a new project" do 

    let!(:client) { Client.create(name: "abc", code: "abc") } 
    let!(:project) { Project.create(name: "abc", client: client) } 
    let!(:user) { User.create(email: "[email protected]", password: "123123123") } 

    # Sign In with user 
    before :each do 
    visit root_url 
    fill_in 'user[email]', with: '[email protected]' 
    fill_in 'user[password]', with: '123123123' 
    find('input[name="commit"]').click 
    end 

    it "saves new project and returns to list of projects on root" do 
    visit root_url 
    click_on 'New Project' 
    expect(current_path).to eq(new_project_path) 

    fill_in "Name", with: "My New Cool Project" 
    fill_in "Details", with: "Praise the sun!" 
    select "urgency_fire", :from => "Urgency" 
    select "status_in_progress", :from => "Status" 
    select "ABC - abc", :from => "Client" 
    fill_in "Due date", with: Time.now.to_s 
    find('input[name="commit"]').click 

    expect(current_path).to eq(root_path) 
    expect(page).to have_text("My New Cool Project") 

    end 
end 

ここでは、テスト出力である:ここで

1) Creating a new project saves new project and returns to list of projects on root 
Failure/Error: %td= project.client.code 

ActionView::Template::Error: 
    undefined method `code' for nil:NilClass 
# ./app/views/dashboard/index.html.haml:17:in `block in _app_views_dashboard_index_html_haml__3165971454273894605_70112485977840' 
# ./app/views/dashboard/index.html.haml:15:in `_app_views_dashboard_index_html_haml__3165971454273894605_70112485977840' 
# ./spec/features/new_project_form_spec.rb:14:in `block (2 levels) in <top (required)>' 
# ------------------ 
# --- Caused by: --- 
# NoMethodError: 
# undefined method `code' for nil:NilClass 
# ./app/views/dashboard/index.html.haml:17:in `block in _app_views_dashboard_index_html_haml__3165971454273894605_70112485977840' 

は、ダッシュボードコントローラです:

class DashboardController < ApplicationController 
    before_action :authenticate_user! 
    def index 
    @projects = Project.includes(:client).all 
    end 
end 

そしてここでは、ダッシュボード、HTML(HAMLです):

.container 
    .row 
    .col-sm-12 
     %p= link_to 'New Project', new_project_path, title: 'New Project' 
     %table 
      %thead 
      %tr 
       %th Client 
       %th Project 
       %th Urgency 
       %th Status  
       %th Due Date 
       %th Assigned To 
      %tbody 
      - @projects.each do |project| 
      %tr 
       %td= project.client.code 
       %td= link_to project.name, project 
       %td= project.urgency 
       %td= project.status 
       %td= project.due_date 
       %td= project.user.count 

そして、あなたはあなたにログインしていない場合、私は、ページ内のログを参照してくださいので、設定した経路を持っている、とあなたはあなたの中にログインしている場合は、ダッシュボードを参照してください。

Rails.application.routes.draw do 

    # devise gem routes 
    devise_for :users 

    # Dashboard 
    authenticated :user do 
     root :to => 'dashboard#index' 
    end 

    # Login 
    devise_scope :user do 
     root to: "devise/sessions#new" 
    end 

    # Projects 
    resources :projects 

    # Send all unknown pages to root 
    if ENV["RAILS_ENV"] == "production" 
     get '*path' => redirect('/') 
    end 

end 

答えて

1

エラーがそこにあることを示唆していますno projectオブジェクト。 let!の呼び出しでそれを作成しています。変数let!は、実行のためにexampleブロック内で収集されています。 exampleブロックが開始され、明示的にbefore :eachというコードが使用されるまで、インスタンス化されていない可能性があります。ただし、この場合はletを使用する必要はありません。

# Given an existing project and logged-in user 
before :each do 
    project = Project.create(name: 'abc', 
    client: Client.create(name: "abc", code: "abc"), 
    code: 'abc') 
    user = User.create(email: "[email protected]", password: "123123123") 

    visit root_url 
    fill_in 'user[email]', with: '[email protected]' 
    fill_in 'user[password]', with: '123123123' 
    find('input[name="commit"]').click 
end 
これは、カピバラは正しくページを読んでいないとは何の関係もありません

From the docs: Use let to define a memoized helper method. The value will be cached across multiple calls in the same example but not across examples.

+0

おかげでグレッグを行う必要があります! –

1

、むしろ、あなたが持っていることを示します:あなたがテストの値を参照しないので、あなたのような何かを試すことができますProjectオブジェクトには関連付けられているクライアントはありません。あなたのコードを考えれば、Clientオブジェクトを作成しようとすると、モデルの検証に失敗する可能性があります。 create!に切り替える必要があります。これは、作成が失敗した場合に発生し、すぐに問題を通知するのに対し、createは保存されていないオブジェクトを返すだけです。さらに、クライアントとプロジェクトを作成する際の検証エラーに関する警告については、test.logを確認してください。

あなたのテストにはいくつかの問題があります。これは、今後の不安定なテストを避けるために修正する必要があります。

  1. beforeブロックは、次回の訪問が呼び出される前にログインが完了したことを確認するために、最後にアサーションが必要です。

    expect(page).to have_content('You are now logged in!') 
    

    または

    ​​
  2. のようなものはcurrent_patheqマッチャーを使用しないでください。 current_pathでeqを使用してJS対応ドライバに移行すると、あらゆる種類のテストフレークが発生します。代わりに、待機中/再試行動作が組み込まれているCapybara提供have_current_pathマッチャを使用してください。ので、代わりにexpect(current_path).to eq(new_project_path)のあなたは、これはそれを固定し、

    expect(page).to have_current_path(new_project_path) 
    
+0

テストのお手伝いをしてくれてありがとうThomas!私はテストを書くことに新しいので、私はフィードバックを感謝します! –

関連する問題