2017-04-03 30 views
0

我知道ActionView::Template::Error: undefined method [] for nil:NilClass是一個常見的錯誤,但沒有其他網頁似乎回答我的問題。我有一個非常簡單的測試,登錄後,進入新的項目頁面,並通過填寫表單來創建一個新項目。但是當我登錄並且rails在Rspec/Capybara中加載儀表板時,我們甚至在測試表單之前沒有正確讀取頁面,並且頁面失敗。Rspec&水豚:ActionView :: Template :: Error:undefined方法`'爲零: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

該錯誤提示有有沒有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. 你之前塊應在年底有一個斷言,以確保登錄已完成下一次訪問調用之前。像

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

    ​​
  2. 東西決不current_path使用eq匹配。一旦你使用eq和current_path移動到一個支持JS功能的驅動程序,將會導致各種各樣的測試問題。而是使用Capybara提供的have_current_path匹配器,它具有內置的等待/重試行爲。因此,而不是expect(current_path).to eq(new_project_path)你應該做

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

感謝您的測試幫助Thomas!我是新手寫測試,所以我很欣賞反饋! –

相關問題