2012-08-29 14 views
6

Od wielu dni próbuję dotrzeć do sedna tego, co to szew jest czymś, co powinno być bardzo łatwe do zrobienia ... Wciąż jednak jestem bardzo nowy w świecie szyn i ruby i ja po prostu nie mogę tego wymyślić ...: pRspec testowanie kolumny counter_cache powracające 0

W każdym razie problem, który mam, polega na tym, że mam kilka kolumn: counter_cache w moim modelu, które działają całkiem nieźle podczas testowania ich ręcznie. Jednak jestem chcąc zrobić rzecz TDD i nie mogę seam przetestować ich w rspec z jakiegoś nieznanego powodu ??

Zresztą tutaj jest przykładem mojego modelu użytkownika (Użytkownika komentuje & media):

class User < ActiveRecord::Base 
    has_many :comments 
    has_many :media, dependent: :destroy 
end 

class Comment < ActiveRecord::Base 
    attr_accessible :content, :user_id 
    belongs_to :commentable, polymorphic: true, :counter_cache => true 
    belongs_to :user, :counter_cache => true 

    validates :user_id, :presence => true 
    validates :content, :presence => true, :length => { :maximum => 255 } 
end 

class Medium < ActiveRecord::Base 
attr_accessible :caption, :user_id 

belongs_to :user, :counter_cache => true 

has_many :comments, as: :commentable 

validates :user_id, presence: true 
validates :caption, length: { maximum: 140 }, allow_nil: true, allow_blank: true 

default_scope order: 'media.created_at DESC' 
end 

Oto próbka z dnia konfiguracji schematu stołu:

create_table "users", :force => true do |t| 
    t.integer "comments_count",   :default => 0, :null => false 
    t.integer "media_count",   :default => 0, :null => false 
end 

create_table "comments", :force => true do |t| 
    t.text  "content" 
    t.integer "commentable_id" 
    t.string "commentable_type" 
    t.datetime "created_at",  :null => false 
    t.datetime "updated_at",  :null => false 
    t.integer "user_id" 
end 

create_table "media", :force => true do |t| 
    t.integer "user_id" 
    t.string "caption" 
    t.datetime "created_at",     :null => false 
    t.datetime "updated_at",     :null => false 
    t.integer "comments_count", :default => 0, :null => false 
end 

I teraz tutaj jest próbka przykład rspec, którego próbowałem:

require 'spec_helper' 

describe "Experimental" do 

    describe "counter_cache" do 
    let!(:user) { FactoryGirl.create(:user)} 

    subject { user } 

    before do 
     @media = user.media.create(caption: "Test media") 
    end 

    its "media array should include the media object" do 
     m = user.media 
     m.each do |e| 
     puts e.caption # Outputting "Test media" as expected 
     end 

     user.media.should include(@media) #This works 
    end 

    it "media_count should == 1 " do # This isnt working? 
     puts user.media_count #Outputting 0 
     user.media_count.should == 1 
    end 
    end 
end 

I na koniec komunikat o błędzie Ten rspec daje mi:

Failures: 

    1) Experimental counter_cache media_count should == 1 
    Failure/Error: user.media_count.should == 1 
     expected: 1 
      got: 0 (using ==) 
    # ./spec/models/experimental_spec.rb:24:in `block (3 levels) in <top (required)>' 

Finished in 0.20934 seconds 
2 examples, 1 failure 

Zauważ, że tak się dzieje dla wszystkich moich kolumn counter_cache we wszystkich modelach. Próbowałem również różnych sposobów testowania tego, ale wszystkie zwracają powyższy komunikat o błędzie.

Naprawdę mam nadzieję, że ktoś może mi w tym pomóc. :)

Dzięki temu stosy z góry! Luke

Odpowiedz

26

Aplikacja counter_cache jest bezpośrednio aktualizowana w bazie danych. To nie będzie miało wpływu na kopię modelu, który został załadowany do pamięci, więc trzeba go przeładować:

it "media_count should == 1 " do 
    user.reload 
    user.media_count.should == 1 
end 

Ale nie sądzę, że jest to, jak chciałbym to sprawdzić. Jak już masz, twój test jest bardzo ściśle powiązany z kodem konfiguracji, który wygląda na to, że wcale nie musi tam być. Co powiesz na coś takiego w wersji samodzielnej:

it "has a counter cache" do 
    user = FactoryGirl.create(:user) 
    expect { 
     user.media.create(caption: "Test media") 
    }.to change { User.last.media_count }.by(1) 
end 
+1

Dzięki za hałdy! Nie zdawałem sobie sprawy, że model został załadowany do pamięci i dlatego konieczne było przeładowanie. –

+0

ok, więc teraz, gdy robimy to z pracą metody user.reload. Ale wtedy chciałem wyczyścić specyfikację i użyć czystszego przykładu, który podałeś, a to nie działa? –

+0

Otrzymuję błąd: –

Powiązane problemy