当请求规范失败(错字或其他异常)时,我们目前面临一个问题,它会影响实际上应该不受影响的其他请求规范。问题是我们使用了很多 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
我试图深入挖掘并看到 save 创建或更新记录的逻辑取决于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
这里的区别在于“工作”规范运行New Record: <boolean>不同。当带有异常的规范在它之前运行时,新记录突然变为真,因此它会生成 SQL 来创建新记录。
接下来我假设一些宝石导致了这个问题,很可能我认为它会是 database_cleaner 但在复制中我或多或少地做同样的事情并且它在那里工作。
问题是我真的被困在调试中,不知道从哪里开始。此外,我不确定是哪个 gem 或我们的代码本身导致了这种情况。
如果您需要更多详细信息,请随时提出任何问题,在此先感谢。