Rails: RSpec - undefined method `cookie_jar' f

2019-05-05 10:49发布

问题:

Rails newbie. Trying to follow Michael Hartl's tutorial.

Stuck trying to add a helper method to simulate log in an RSpec test:

describe "when the a user has logged in and attempts to visit the page" do
    let(:user) { FactoryGirl.create :user }
    before do 
      log_in user
    end
    it "should redirect the user to next page" do
      specify { response.should redirect_to loggedin_path }
    end
  end

In my spec/support/utilities.rb:

def log_in user
    visit root_path
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    click_button "Log in"
    cookies[:remember_token] = user.remember_token
end

Error:

Failure/Error: log_in user
     NoMethodError:
       undefined method `cookie_jar' for nil:NilClass

What gives?

Edit, full stack trace:

Index page when the a user has logged in and attempts to visit the page should redirect the user to next page
     Failure/Error: log_in user
     NoMethodError:
       undefined method `cookie_jar' for nil:NilClass
     # ./spec/support/utilities.rb:8:in `log_in'
     # ./spec/features/pages/index_spec.rb:20:in `block (3 levels) in <top (required)>'

回答1:

RSpec is very particular about the directory that you place your tests. If you put the test in the wrong directory, it won't automagically mix-in the various test helpers that setup different types of tests. It seems your setup is using spec/features which is not an approved default directory (spec/requests, spec/integration, or spec/api).

Based on the tutorial page, I'm not sure how they have the spec_helper.rb file setup. Though the examples so they are using spec/requests to hold the tests.

You can force RSpec to recognize another directory for request specs by using on of the following:

Manually add the proper module to the test file:

# spec/features/pages/index_spec.rb
require 'spec_helper'

describe "Visiting the index page" do

  include RSpec::Rails::RequestExampleGroup

  # Rest of your test code
  context "when the a user has logged in and attempts to visit the page" do
    let(:user) { FactoryGirl.create :user }

    before do 
      log_in user
    end

    specify { response.should redirect_to loggedin_path }
  end

end

Include this in your spec/spec_helper.rb file:

RSpec::configure do |c|
  c.include RSpec::Rails::RequestExampleGroup, type: :request, example_group: {
    file_path: c.escaped_path(%w[spec (features)])
  }
end

Since this is a tutorial I'd recommend following the standard of including require 'spec_helper' at the top of the spec file and that your actual spec/spec_helper.rb file has require 'rspec/rails'

A minor note, you don't need to put a specify inside of an it block. They are aliases of each other, so just use one.

context "when the a user has logged in and attempts to visit the page" do
  let(:user) { FactoryGirl.create :user }

  before do 
    log_in user
  end

  # All of the following are the same

  it "redirects the user to next page" do
    response.should redirect_to loggedin_path
  end

  it { response.should redirect_to loggedin_path }

  specify "redirects the user to next page" do
    response.should redirect_to loggedin_path
  end

  specify { response.should redirect_to loggedin_path }
end

Note, according to the documentation for capybara, you should be able to put your capybara tests into spec/features. To make this work, ensure you are loading require 'capybara/rspec' in your spec_helper or test spec file directly.

However, looking at the source, I didn't see where they are automatically including that directory. You can also try adding the tag type: :feature to the outer describe block in your test file. Though the more likely solution is to use spec/requests.



回答2:

Shouldn't you have the "user" argument of the method enclosed in parenthesis?

def log_in(user)
    visit root_path
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    click_button "Log in"
    cookies[:remember_token] = user.remember_token
end


回答3:

To have a mock cookie jar, you must have either rack-test or rspec-rails gem included in your Gemfile. I think maybe you have included just rspec and maybe missed out rspec-rails.

You also need to ensure you've configured the session store as follows:

config.session_store = :cookie_store

This must have been done in either config/application.rb or some file under config/initializers. If you have configured this in config/environments/development.rb or somewhere else, the Test environment will not be able to pick it up.