當請求規範失敗時(錯字或其他異常),我們當前會面臨一個問題,它會影響實際上應該不受影響的其他請求規範。問題是,我們用很多的寶石,所以我試圖創建一個最小的再現應用程序(沒有成功,https://github.com/tak1n/reproduction)請求規範順序依賴失敗(在登錄時爲創建用戶更新而創建的SQL錯誤)
詳細的問題:
我們有我們需要登錄的用戶的請求規範。對於用戶認證,我們使用設計,因此我們使用Warden :: Test :: Helpers在請求規格中登錄用戶。在用戶登錄時,設計會自動更新一些與用戶相關的屬性(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
當規格不同的順序運行(非失敗的第一個,然後在它拼寫錯誤或異常SPEC)我得到這個:https://gist.github.com/tak1n/6eb24693226d8e6a713c0865ea1bebd5
這裏的區別是「工作」規格運行New Record: <boolean>
是不同的。當具有異常的規範運行之前,新記錄突然變爲true,因此它會生成SQL以創建新記錄。
接下來我假設一些寶石導致了這個問題,最有可能的是我認爲這將是database_cleaner,但在複製中,我做的或多或少是相同的,它在那裏工作。
問題是我真的被困在調試中,並不確定在哪裏繼續。此外,我不確定哪個寶石或我們的代碼本身造成這種情況。
如果您需要更多詳細信息,請隨時提出任何問題,提前致謝。
你有沒有嘗試將'login(user)'調用放在你的'it'塊中?我認爲這將確保他們運行並創建用戶,即使在塊中降低了引發的異常。 – DiegoSalazar
@diego。greyrobot是的我試圖把用戶創建和用戶登錄到'it'塊中,但是與'before do'基本相同的結果'before(:each)do'因此它已經爲每個spec示例。 –