2016-03-15 54 views
1

我有这样的代码来验证频道的订阅者:使用cookies.signed [:USER_ID]在水豚测试

​​

,一切工作正常。问题出在功能测试中。 当我运行这个测试:

require 'rails_helper' 

feature 'Chat room' do 
    scenario "send one message" do 
    user = create(:user) 
    login_as(user, :scope => :user) 

    expect { 
     fill_in 'message', with: 'hello friend' 
     click_button 'Send' 
     byebug 
    }.to change(Message, :count).by(1) 
    expect(current_path).to eq root_path 
    expect(page).to have_content 'hello friend' 
    end 
end 

测试日志,说,“未经授权的连接尝试被拒绝”。由于cookie为空,因此无法进行身份验证。

那么如何在水豚测试中设置cookie?

我试过这样做cookies.signed[:user_id] = user.id在测试中,但它不起作用。

如何在测试中设置像这样的饼干cookies.signed[:user_id] = user.id

+0

你是什么login_as'的'界定,而/你什么时候实际访问的网页的工作? –

回答

0

您还应该将用户标识存储在会话中 - 而不是存储在cookie本身*中。该cookie应该只包含一个会话标识符。

而且你应该把你的验证逻辑收集到一个地方,这样它就不会在你的控制器中被复制。

module AuthenticationHelper 
    def current_user 
    @current_user || = User.find_by(session[:user_id]) 
    end 

    def signed_in? 
    current_user.is_a?(User) 
    end 

    def sign_in(user) 
    reset_session # prevents session fixation 
    @current_user = user 
    session[:user_id] = user.id 
    end 

    def sign_out 
    reset_session 
    @current_user = nil 
    end 

    def authorize! 
    raise AuthenticationError unless current_user 
    end 
end 

这应该是在你的应用程序的唯一的地方它知道用户是如何在会议上连载。更好的办法是使用Warden而不是重新发明轮子。

当测试控制器和视图,你可以简单的存根current_user方法 - 然而,对于功能规格,你实际上应该通过实际登录的步骤向用户发送:

def sign_user_in(user) 
    visit new_session_path 
    fill_in 'Email', with: user.email 
    fill_in 'Password', with: user.password 
    click_button 'Log in' 
end 

这可以确保您的验收测试实际上覆盖系统,并避免将任何底层系统知识纳入您的测试。然而,渲染登录页面会导致性能损失,这会大大降低测试套件的速度。

作为一种变通方法,您可以直接发送POST请求:

def sign_user_in_directly(user) 
    page.driver.post(sessions_path, { 
    params: { 
     email: user.email, 
     password: user.password 
    } 
    }) 
end 

注意,这取决于驱动程序 - 一些javascript驱动程序可能支持或不支持这一点。

+0

* Rails中的默认会话存储是* cookie存储* - 但您仍然应该使用会话机制,因为它可以帮助您防止会话固定和基于cookie的攻击。 http://guides.rubyonrails.org/security.html#session-hijacking – max

0

假设你打电话的login_as是来自Warden测试助手,它的功能是设置好的,以便下一个请求在响应中设置会话cookie。因此,您可能需要在致电login_as后访问一个页面。此外,由于单击“发送”是异步的,因此在检查Message.count已更改之前,需要等待某些内容发生更改,如果您想要非片状测试,那么您实际上不应该使用带有current_path的.eq。因此,所有的组合像

#don't visit the page where you can fill in the message before calling login_as 


scenario "send one message" do 
    user = create(:user) 
    login_as(user, :scope => :user) 
    visit 'the path to the page where you can fill in a message' 
    expect { 
    fill_in 'message', with: 'hello friend' 
    click_button 'Send' 
    expect(page).to have_css('#messages', text:'hello friend') # adjust selector depending on where the message is supposed to appear 
    expect(page).to have_current_path(root_path) 
    }.to change(Message, :count).by(1) 
end 

应该为你