在 Rspec 请求测试中使用 Session、Cookies 或 Current_something
Using Session, Cookies or Current_something in Rspec request tests
我正在努力遵循新的 Rails 测试惯例来处理我正在从事的这个新项目。因此,我设置了单元测试、请求测试和功能测试。问题是在请求测试中,不支持 Capybara 和会话信息。
除了 Devise 设置的 current_user 方法外,我的应用程序还有另一个类似的方法,称为 current_client。对于我的某些控制器,我需要检查 current_user 是否已登录。这适用于 Devise authenticate_user!在 before_action 中调用。但对于某些控制器,我还需要先检查客户端是否被 selected(例如,如果你想添加事务,它们需要与当前正在处理的客户端绑定)。
所以我添加了另一个 before_action 方法来检查客户端是否也被 selected。这在 Capybara 的功能测试中效果很好,我可以模拟用户登录和用户 selecting 客户端进行处理。但是在请求测试中,它不起作用。
我首先测试尝试在没有用户登录的情况下访问端点,但响应不成功(应该如此),它重定向到登录页面。但随后我需要 运行 我的测试与用户登录和客户端 selected。 Devise helpers 提供了一个 sign_in(user) 方法。但是我无法让我的 current_user 方法工作,而且我似乎无法正确设置它。因此,这些测试失败并重定向到另一个页面,要求用户 select 一个客户端。
我已经尝试了很多我看到的建议。就像尝试存根 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
一旦用户select成为要处理的客户端
,它就是这样设置的
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.
我通过使用 DHH 自己建议的解决方案找到了解决方法。
与其尝试对 current_client 变量进行存根或尝试在 ActionDispatch::Cookies 的内部设置一些东西,您只需要对任何控制器执行 POST 或 GET 调用负责设置我的 current_client 变量。
所以对我来说,解决方案是将以下代码放在 before do 块中
before do
sign_in(user)
get select_client_path, params: {id: client.id}
end
我正在努力遵循新的 Rails 测试惯例来处理我正在从事的这个新项目。因此,我设置了单元测试、请求测试和功能测试。问题是在请求测试中,不支持 Capybara 和会话信息。
除了 Devise 设置的 current_user 方法外,我的应用程序还有另一个类似的方法,称为 current_client。对于我的某些控制器,我需要检查 current_user 是否已登录。这适用于 Devise authenticate_user!在 before_action 中调用。但对于某些控制器,我还需要先检查客户端是否被 selected(例如,如果你想添加事务,它们需要与当前正在处理的客户端绑定)。
所以我添加了另一个 before_action 方法来检查客户端是否也被 selected。这在 Capybara 的功能测试中效果很好,我可以模拟用户登录和用户 selecting 客户端进行处理。但是在请求测试中,它不起作用。
我首先测试尝试在没有用户登录的情况下访问端点,但响应不成功(应该如此),它重定向到登录页面。但随后我需要 运行 我的测试与用户登录和客户端 selected。 Devise helpers 提供了一个 sign_in(user) 方法。但是我无法让我的 current_user 方法工作,而且我似乎无法正确设置它。因此,这些测试失败并重定向到另一个页面,要求用户 select 一个客户端。
我已经尝试了很多我看到的建议。就像尝试存根 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
一旦用户select成为要处理的客户端
,它就是这样设置的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.
我通过使用 DHH 自己建议的解决方案找到了解决方法。
与其尝试对 current_client 变量进行存根或尝试在 ActionDispatch::Cookies 的内部设置一些东西,您只需要对任何控制器执行 POST 或 GET 调用负责设置我的 current_client 变量。
所以对我来说,解决方案是将以下代码放在 before do 块中
before do
sign_in(user)
get select_client_path, params: {id: client.id}
end