2014-01-24 66 views
0

我有以下規格:RSpec的不比較對象正確

require 'spec_helper' 

describe Page do 
    it "has a valid factory" do 
    create(:page).should be_valid 
    end 

    it "is invalid without a title" do 
    build(:page, title: nil).should_not be_valid 
    end 

    it "finds record" do 
    page = create(:page, title: 'heyo') 
    Page.unscoped.where(:title => 'heyo').should == page 
    end 

    it "finds record with same attributes" do 
    page = create(:page, title: 'heyo') 
    Page.unscoped.where(:title => 'heyo').first.attributes.each do |name, val| 
     expect(page[name]).to eq(val) 
    end 
    end 
end 

我有以下工廠:

model_statuses = ['published', 'draft'] 
FactoryGirl.define do 
    factory :page do 
    title   { Faker::Lorem.word + ' Page' } 
    slug   { title ? title.parameterize : nil } 
    intro   { Faker::Lorem.sentence 10 } 
    content  { Faker::Lorem.sentences(5).join ' ' } 
    status  { model_statuses.sample } 
    end 
end 

測試失敗:

Failures: 

    1) Page finds record with same attributes 
    Failure/Error: expect(page[name]).to eq(val) 

     expected: Fri, 24 Jan 2014 23:33:47 MSK +04:00 
      got: Fri, 24 Jan 2014 23:33:47 MSK +04:00 

     (compared using ==) 

     Diff: 
    # ./spec/models/page_spec.rb:20:in `block (3 levels) in <top (required)>' 
    # ./spec/models/page_spec.rb:19:in `each' 
    # ./spec/models/page_spec.rb:19:in `block (2 levels) in <top (required)>' 

    2) Page finds record 
    Failure/Error: Page.unscoped.where(:title => 'heyo').should == page 
     expected: #<Page id: 1, slug: "heyo", title: "heyo", intro: "Sed sint et nesciunt earum libero eveniet est cupid...", content: "A sunt ab exercitationem quas ex incidunt numquam. ...", created_at: "2014-01-24 19:33:47", updated_at: "2014-01-24 19:33:47", status: "draft"> 
      got: [#<Page id: 1, slug: "heyo", title: "heyo", intro: "Sed sint et nesciunt earum libero eveniet est cupid...", content: "A sunt ab exercitationem quas ex incidunt numquam. ...", created_at: "2014-01-24 19:33:47", updated_at: "2014-01-24 19:33:47", status: "draft">] (using ==) 

爲什麼這些對象他們的屬性是不一樣的,我如何正確檢查對象的平等?

回答

1

兩個錯誤的來源是相同的。

您正在比較其中一個日期created_at,updated_at,並且它們似乎沒有相同的值。

請注意,日期僅在打印爲字符串時纔會轉到第二個日期 - 它們可能會在較低的級別上有所不同。

要麼從比較中排除日期,要麼在代碼中對失敗站點進行提升/檢查,以查看兩個項目之間的小數秒是否不同。

您可以使用的另一個技巧是在規範的範圍內將Time.now/Time.new截斷,以便始終獲得一致的結果。

通常情況下,您會在規範的上下文中的每個塊之前刪除/濫用Time.now。您希望儘可能縮小範圍,因爲如果您不仔細的操作,重寫該方法可能會產生各種奇怪的副作用。

+0

謝謝。存根'Time.now'的最佳方法是什麼?在RSpec中通常如何比較對象?什麼是最佳實踐? – leemour

+0

我將如何在代碼中提出/檢查以查看實際值? – leemour

+0

@leemour當我說舉起/檢查時,我的意思是在失敗的測試中調用'raise page.inspect',例如在您的「查找記錄」示例中。 – TreyE

2

我發現問題是在測試中比較不同的對象。

以下測試:

it "finds record" do 
    page = create(:page, title: 'heyo') 
    Page.unscoped.where(:title => 'heyo').should == page 
    end 

當你到了這個測試,你已經有一個page對象從"has a valid factory"測試。因此在執行此測試後,您有兩個頁面對象,第一個標題爲nil,第二個標題爲heyo。現在,當您嘗試在下一行中與should匹配時,您的Page.unscoped.where(:title => 'heyo')確實會返回預期結果,即標題爲'heyo'的Page對象數組。你正在獲得一個數組,並且你正在比較這個數組和一個Object,所以這會失敗。

然後,您的第二個測試"finds record with same attributes"失敗的原因是因爲您期望第一個Page對象等於last對象,所以這也將失敗。

所以修復將是對以下兩項測試:

it "finds record" do 
    page = create(:page, title: 'heyo') 
    Page.unscoped.where(:title => 'heyo').last.should == page 
    end 

    it "finds record with same attributes" do 
    page = create(:page, title: 'heyo') 
    Page.unscoped.where(:title => 'heyo').last.attributes.each do |name, val| 
     expect(page[name]).to eq(val) 
    end 
    end 

注意在兩個測試中使用的last

database_cleaner gem是你可能感興趣的東西,它允許你在每次測試前清理數據庫。推薦看看它。

+0

謝謝,我完全忘記了以前的保存。添加'.last'使''找到記錄''通過。但''發現具有相同屬性的記錄「'失敗,我檢查看到:'(byebug)page.updated_at.to_f 1390598731.7451882(byebug)page_saved.updated_at.to_f 1390598731.745188'所以有時差。現在我很困惑。爲什麼一個測試通過,其他失敗? – leemour