2016-12-06 38 views
0

我從Rails的升級我的應用程序4.0至4.1(對我的方式,以4.2)重裝對象,有這樣的測試,是失敗的:重裝在rspec的一個ActiveRecord對象更新數據庫記錄,而不是從DB

describe "#restore_disabled_account" do 
    let(:username) { 'username' } 
    let(:email) { '[email protected]' } 
    let(:m3_user) { create(:user, username: username, 
            email: email, 
           archived: false, 
        propagate_in_test_mode: true) } 
    let(:m2_user) { Maestro2::User.where(UserID: m3_user.id).first } 

    before do 
    m3_user.disable_account 
    end 

    it "unarchives the account" do 
    m3_user.restore_disabled_account 
    m3_user.reload 
    expect(m3_user.archived).to be_falsey 
    end 
end 

我已驗證數據庫包含此測試開始時具有預期屬性的記錄。在調試測試時,我在重裝語句之前停下來,發現數據庫記錄已按預期更新(歸檔爲false,其他屬性按預期更新)。我也可以看到m3_user對象已經用相同的屬性進行了更新。當我繼續運行重新加載步驟並查詢數據庫時,我可以看到記錄已恢復到其原始狀態,與內存中的對象一樣。測試然後失敗,因爲m3_user.archived爲true。

有人可以告訴我爲什麼嗎?我的套件中的所有測試都在開始升級之前通過。該應用程序正在使用Ruby 2.2.4,Rails的4.1.16,rspec的3.5.3和RSpec-導軌3.5.2

作爲參考,這兩個用戶類的方法調用低於:

def disable_account 
    self.update_attributes(username: "disabled_#{id}_#{username}", 
          email: "disabled_#{id}_#{email}", 
         archived: true) 
end 

def restore_disabled_account 
    self.update_attributes(username: username.gsub(/^disabled_#{id}_/, ''), 
          email: email.gsub(/^disabled_#{id}_/, ''), 
         archived: false) 
end 
+0

這與問題無關,但「#{username}」是多餘的。你插入的所有東西都是變量本身,所以它只需要'username:username'等。插入是指當字符串不僅包含動態Ruby代碼時。 – sixty4bit

+0

也可以請您添加'#restore_disabled_account'方法的內容,並嘗試從'let!'中刪除爆炸'!'? – sixty4bit

+0

我已添加您要求的代碼。消除爆炸並不會改變結果,不幸的是。 – Warren

回答

0

的簡短的回答:事實證明,ActiveRecord 4.1改變了reload方法來調用一個新的私有方法reset_changes。我的用戶類也有reset_changes方法,所以我的方法覆蓋了本來應該調用的方法。

漫長的答案:我越看越這個,我越懷疑我的用戶模型是獨一無二的。其他測試使用reload按預期執行。然後我在用戶中遇到了reset_changes方法。在看到它做了什麼之後(用前面的值更新數據庫記錄),我放下了一個puts語句,以便看看它是否被調用。一旦確認,我傾倒來電回溯,指向我https://github.com/rails/rails/blob/4-1-stable/activerecord/lib/active_record/attribute_methods/dirty.rb#L37

我已將我的用戶模型方法更改爲undo_changes,我的規格爲綠色。

相關問題