【发布时间】:2019-05-17 13:49:25
【问题描述】:
我正在尝试在我正在从事的这个新项目中遵循新的 Rails 测试约定。因此我设置了单元测试、请求测试和功能测试。问题是在请求测试中,不支持 Capybara 和会话信息。
除了由 Devise 设置 current_user 方法外,我的应用程序还有另一个类似的方法,称为 current_client。对于我的一些控制器,我需要检查 current_user 是否已登录。这适用于 Devise authenticate_user!在 before_action 中调用。但是对于一些控制器,我还需要检查是否首先选择了一个客户端(例如,如果你想添加事务,它们需要与当前正在处理的客户端绑定)。
所以我添加了另一个 before_action 方法来检查是否还选择了客户端。这在 Capybara 的功能测试中效果很好,我可以在其中模拟用户登录和用户选择要处理的客户端。但是在请求测试中,它不起作用。
我首先测试尝试在没有用户登录的情况下访问端点并且响应不成功(应该如此)并且它重定向到登录页面。但是然后我需要在用户登录并选择客户端的情况下运行我的测试。设计助手提供了一个 sign_in(user) 方法。但是我无法让我的 current_user 方法工作,而且我似乎无法正确设置它。因此,这些测试失败并重定向到另一个页面,要求用户选择客户端。
我已经尝试了很多我看到的建议。就像尝试存根 current_client 方法一样,尝试向 GET 调用提供会话信息。我什至尝试检查 Devise 源代码,以了解他们如何在 Rspec 中模拟 current_user 方法,但无法真正找到神奇之处。
这里是代码
current_client 方法如下所示
def current_client
current_client ||= Client.find(session[:client_id]) if session[:client_id]
rescue ActiveRecord::RecordNotFound
current_client = nil
end
这就是用户选择要处理的客户端后的设置方式
def set_current_client(client)
session[:client_id] = client.id
end
这是我的测试文件中的代码 我首先创建了 2 个用户,以便我可以测试用户 1 不能访问用户 2 的事务。 (我正在使用 FactoryBot) 然后我创建 2 个客户端(每个用户一个)
RSpec.describe "Rooms", :type => :request do
let!(:user) {create(:user)}
let!(:user2) {create(:user2)}
let!(:client) {create(:client, user: user)}
let!(:client) {create(:client, user: user2)}
以下作品
describe 'User Not Signed In' do
describe 'GET #index' do
subject { get transact_path}
it "returns an unsuccessful response" do
subject
expect(response).to_not be_successful
end
it "redirects to sign in page" do
subject
expect(response).to redirect_to (new_user_session_path)
end
end
以下没有。 sign_in(user) 方法在 before 块中起作用,并且不会重定向到登录页面。但是,响应不成功,因为 current_client 没有设置,我在 before 块中尝试了很多方式设置它没有成功。
describe 'User Signed In' do
before do
sign_in(user)
end
describe 'GET #index' do
it "returns a successful response" do
get transact_path
expect(response).to be_successful
end
end
end
我了解最佳实践已远离控制器测试,因为理论上呈现的视图或分配的实例变量与控制器没有任何关系。但就我而言,我只是想测试我的端点,现在我不能,因为我无法设置我的 current_client。
【问题讨论】:
-
所以,重定向发生是因为
current_client未设置?如果没有current_client,你有没有重定向的before_filter?您是否尝试过在规范中添加before并添加session[:client_id] = your client id session。只需确保在发出请求之前已设置它即可。 -
尝试在你的代码中放置一些断点,看看什么被击中以及会话状态是什么
-
如果没有设置 current_client,我确实有一个 before_action 重定向。至于在 Rspec 的 before 子句中设置会话变量,会话变量在新的请求测试中不可用,所以我不能这样做这样。我还尝试对 current_client 方法进行存根并为其分配一个客户端 ID……仍然没有用。我不敢相信请求规范没有任何东西可以测试这些东西。
标签: ruby-on-rails ruby rspec