请求规范顺序相关失败(为登录时设计用户更新创建了错误的 SQL)
Request spec order dependent failure (wrong SQL created for devise user update on login)
我们目前面临一个问题,当一个请求规范失败(拼写错误或其他异常)时,它会影响其他实际上应该不受影响的请求规范。问题是我们使用了很多 gem,所以我尝试创建一个最小的复制应用程序(没有成功,https://github.com/tak1n/reproduction)
问题详细:
我们有一个需要登录用户的请求规范。对于用户身份验证,我们使用设计,因此我们使用 Warden::Test::Helpers 在请求规范中登录用户。 Devise 在用户登录时自动更新一些与用户相关的属性(last_sign_in_at、last_sign_in_ip 等)。
这里的问题是,当它试图保存执行此更改的用户时,最终结果是 INSERT INTO 用户而不是 UPDATE 用户,因此它崩溃了。
这是我们应用程序的示例规范:
require 'rails_helper'
RSpec.describe 'Suggestions API' do
let(:user) { FactoryGirl.create(:user, :professional) }
before do
login(user) # same as in https://github.com/tak1n/reproduction/blob/master/spec/support/request_macros.rb#L6
end
describe '/suggestions.json', :vcr do
context 'with non saved filter' do
# some setup stuff here (setup proper objects in db)
# also params are defined here through let(:params) { ... }
it 'returns proper suggestions' do
Suggestion.refresh!
get '/suggestions.json', paramst
expect(json.count).to eq(2)
expect(json.first['id']).to eq(sug2.id)
expect(json.second['id']).to eq(sug1.id)
end
end
context 'with saved filter' do
# some setup stuff here (setup proper objects in db)
# also params are defined here through let(:params) { ... }
it 'returns proper suggestions' do
Suggestion.refresh!
get '/suggestions.json', params
expect(json.count).to eq(2)
expect(json.first['id']).to eq(sug2.id)
expect(json.second['id']).to eq(sug1.id)
end
end
end
end
这样做的结果应该是第一个规范由于错字 paramst
而失败,但它也影响了第二个规范:
这是规范 运行:https://gist.github.com/tak1n/102c1aa121b66e0ab56602b76f911ec0
我试图深入挖掘,发现保存创建或更新记录的逻辑取决于https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb#L85
接下来我尝试输出 @new_record
在那种情况下的结果。
def new_record?
sync_with_transaction_state
puts "New record: #{@new_record}" if self.class == User
@new_record
end
我得到以下信息:https://gist.github.com/tak1n/330560a3a108abc8fce4d105a48ac444
当规格 运行 以不同的顺序排列时(首先没有失败,然后是有拼写错误或异常的规格)我得到了这个:https://gist.github.com/tak1n/6eb24693226d8e6a713c0865ea1bebd5
此处的区别是 "working" 规范 运行 New Record: <boolean>
不同。当在新记录之前有异常 运行s 的规范突然变为真,因此它生成 SQL 以创建新记录。
接下来我假设一些 gem 导致了这个问题,很可能我认为它会是 database_cleaner 但在复制品中我或多或少做了同样的事情并且它起作用了。
问题是我一直在调试,不知道从哪里开始。我也不确定是哪个 gem 或我们的代码本身导致了这个问题。
如果您需要更多详细信息,请随时提出任何问题,在此先感谢。
问题似乎是由设计异步引起的 (https://github.com/mhfs/devise-async)。
有关详细信息,请参阅 https://github.com/rails/rails/issues/26038 and https://github.com/mhfs/devise-async/issues/96。
我们目前面临一个问题,当一个请求规范失败(拼写错误或其他异常)时,它会影响其他实际上应该不受影响的请求规范。问题是我们使用了很多 gem,所以我尝试创建一个最小的复制应用程序(没有成功,https://github.com/tak1n/reproduction)
问题详细:
我们有一个需要登录用户的请求规范。对于用户身份验证,我们使用设计,因此我们使用 Warden::Test::Helpers 在请求规范中登录用户。 Devise 在用户登录时自动更新一些与用户相关的属性(last_sign_in_at、last_sign_in_ip 等)。
这里的问题是,当它试图保存执行此更改的用户时,最终结果是 INSERT INTO 用户而不是 UPDATE 用户,因此它崩溃了。
这是我们应用程序的示例规范:
require 'rails_helper'
RSpec.describe 'Suggestions API' do
let(:user) { FactoryGirl.create(:user, :professional) }
before do
login(user) # same as in https://github.com/tak1n/reproduction/blob/master/spec/support/request_macros.rb#L6
end
describe '/suggestions.json', :vcr do
context 'with non saved filter' do
# some setup stuff here (setup proper objects in db)
# also params are defined here through let(:params) { ... }
it 'returns proper suggestions' do
Suggestion.refresh!
get '/suggestions.json', paramst
expect(json.count).to eq(2)
expect(json.first['id']).to eq(sug2.id)
expect(json.second['id']).to eq(sug1.id)
end
end
context 'with saved filter' do
# some setup stuff here (setup proper objects in db)
# also params are defined here through let(:params) { ... }
it 'returns proper suggestions' do
Suggestion.refresh!
get '/suggestions.json', params
expect(json.count).to eq(2)
expect(json.first['id']).to eq(sug2.id)
expect(json.second['id']).to eq(sug1.id)
end
end
end
end
这样做的结果应该是第一个规范由于错字 paramst
而失败,但它也影响了第二个规范:
这是规范 运行:https://gist.github.com/tak1n/102c1aa121b66e0ab56602b76f911ec0
我试图深入挖掘,发现保存创建或更新记录的逻辑取决于https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb#L85
接下来我尝试输出 @new_record
在那种情况下的结果。
def new_record?
sync_with_transaction_state
puts "New record: #{@new_record}" if self.class == User
@new_record
end
我得到以下信息:https://gist.github.com/tak1n/330560a3a108abc8fce4d105a48ac444
当规格 运行 以不同的顺序排列时(首先没有失败,然后是有拼写错误或异常的规格)我得到了这个:https://gist.github.com/tak1n/6eb24693226d8e6a713c0865ea1bebd5
此处的区别是 "working" 规范 运行 New Record: <boolean>
不同。当在新记录之前有异常 运行s 的规范突然变为真,因此它生成 SQL 以创建新记录。
接下来我假设一些 gem 导致了这个问题,很可能我认为它会是 database_cleaner 但在复制品中我或多或少做了同样的事情并且它起作用了。
问题是我一直在调试,不知道从哪里开始。我也不确定是哪个 gem 或我们的代码本身导致了这个问题。
如果您需要更多详细信息,请随时提出任何问题,在此先感谢。
问题似乎是由设计异步引起的 (https://github.com/mhfs/devise-async)。
有关详细信息,请参阅 https://github.com/rails/rails/issues/26038 and https://github.com/mhfs/devise-async/issues/96。