2014-10-10 25 views
0

我对RoR比较陌生,经历了Hart的教程并遇到了一些小问题。我希望你能帮助!Rails教程8.3认证测试未通过

我完成了第8章,并试图让最后一个测试通过,但我一直失败。我是新来的所有这一切,所以任何帮助将不胜感激。我看了其他类似的问题,但并未真正找到我的解决方案。而且......我知道这只是一个测试,但我对这些事情是超级肛门的,我不会继续前进,直到我知道100%我做错了什么。断开连接在哪里?我在这里没有看到什么?

故障测试

No DRb server is running. Running in local process instead ... .........................................F......

Failures:

1) Authentication signin followed by signout Failure/Error: before { click_link "Sign out" } Capybara::ElementNotFound: Unable to find link "Sign out" # ./spec/requests/authentication_pages_spec.rb:34:in `block (4 levels) in '

Finished in 0.67649 seconds 48 examples, 1 failure

Failed examples:

rspec ./spec/requests/authentication_pages_spec.rb:35 # Authentication signin followed by signout

Randomized with seed 40273


Authentication_pages_spec.rb文件

require 'spec_helper' 

describe "Authentication" do 

    subject { page } 

    describe "signin" do 
    before { visit signin_path } 

    describe "with invalid information" do 
     before { click_button "Sign in" } 

     it { should have_title('Sign in') } 
     it { should have_selector('div.alert.alert-error') } 

     describe "after visiting another page" do 
     before { click_link "Home" } 
     it { should_not have_selector('div.alert.alert-error') } 
     end 
    end 

    describe "with valid information" do 
     let(:user) { FactoryGirl.create(:user) } 
     before { sign_in user } 

     it { should have_title(user.name) } 
     it { should have_link('Profile',  href: user_path(user)) } 
     it { should have_link('Settings', href: edit_user_path(user)) } 
     it { should have_link('Sign out', href: signout_path) } 
     it { should_not have_link('Sign in', href: signin_path) } 
    end 

    describe "followed by signout" do 
     before { click_link "Sign out" } 
     it { should have_link('Sign in') } 
    end 
    end 
end 
end 

sessions_controller.rb代码

class SessionsController < ApplicationController 

    def new 
    end 

    def create 
    user = User.find_by(email: params[:session][:email].downcase) 
    if user && user.authenticate(params[:session][:password]) 
     sign_in user 
     redirect_to user 
    else 
     flash.now[:error] = 'Invalid email/password combination' 
     render 'new' 
    end 
    end 

    def destroy 
    sign_out 
    redirect_to root_url 
    end 
end 

sessions_helper.rb代码

module SessionsHelper 

    def sign_in(user) 
    remember_token = User.new_remember_token 
    cookies.permanent[:remember_token] = remember_token 
    user.update_attribute(:remember_token, User.digest(remember_token)) 
    self.current_user = user 
    end 

    def signed_in? 
    !current_user.nil?  
    end 
    def current_user=(user) 
    @current_user = user 
    end 

    def current_user 
    remember_token = User.digest(cookies[:remember_token]) 
    @current_user ||= User.find_by(remember_token: remember_token) 
    end 

    def sign_out 
    current_user.update_attribute(:remember_token, User.digest(User.new_remember_token)) 
    cookies.delete(:remember_token) 
    self.current_user = nil 
    end 
end 

回答

0

你只在一个测试"with valid information"创建FactoryGirl新用户。当你去下一次测试时,你没有这个用户,所以你需要在do end区块"with valid information"中进行这个测试。

describe "Authentication" do 

    subject { page } 

    describe "signin" do 
    # You run it before all tests in this block 
    before { visit signin_path } 

    describe "with invalid information" do 
     # So, here you visit signin_path and click "Sign in" link 
     before { click_button "Sign in" } 

     it { should have_title('Sign in') } 
     it { should have_selector('div.alert.alert-error') } 

     describe "after visiting another page" do 
     before { click_link "Home" } 
     it { should_not have_selector('div.alert.alert-error') } 
     end 
    end 

    # Before this test you only visit signin_path 
    describe "with valid information" do 
     # After this you create new user with FactoryGirl... 
     let(:user) { FactoryGirl.create(:user) } 
     # ...and sign him in (before every test in this block) 
     before { sign_in user } 

     it { should have_title(user.name) } 
     it { should have_link('Profile',  href: user_path(user)) } 
     it { should have_link('Settings', href: edit_user_path(user)) } 
     it { should have_link('Sign out', href: signout_path) } 
     it { should_not have_link('Sign in', href: signin_path) } 
    end 

    # Here you again visit signin_path, but you don't have FactoryGirl user. 
    # You can have this user, if you move this block to previous: "with valid information" 
    describe "followed by signout" do 
     before { click_link "Sign out" } 
     it { should have_link('Sign in') } 
    end 
    end 
end 

因此,重构你的代码是这样的:

describe "with valid information" do 
    let(:user) { FactoryGirl.create(:user) } 
    before { sign_in user } 

    it { should have_title(user.name) } 
    it { should have_link('Profile',  href: user_path(user)) } 
    it { should have_link('Settings', href: edit_user_path(user)) } 
    it { should have_link('Sign out', href: signout_path) } 
    it { should_not have_link('Sign in', href: signin_path) } 

    describe "followed by signout" do 
    before { click_link "Sign out" } 
    it { should have_link('Sign in') } 
    end 
end 

这应该帮助。

完成RailsTutorial之后,我建议您阅读"Everyday Rails: Testing with RSpec"should模式在测试中相当过时,并且使用expect -> to模式代替是一种很好的做法。

+0

太棒了!这完全有意义,它的工作!非常感谢你的帮助和评论,这些评论确实帮助我了解正在发生的事情的过程。我希望Rails指南有这个。我也会检查一下这本书! – Igor 2014-10-10 23:10:17