Rspec тестирование возвращения столбца counter_cache 0

Уже несколько дней я пытаюсь докопаться до сути того, что должно быть очень легко сделать... Однако я все еще очень плохо знаком с миром рельсов и рубинов, и я просто не могу разобраться с этим...:п

В любом случае, у меня проблема в том, что у меня есть несколько столбцов: counter_cache в моей модели, которые работают очень хорошо при тестировании их вручную. Однако я хочу сделать TDD, и я не могу шов, чтобы проверить их в rspec по какой-то неизвестной причине??

В любом случае, вот пример моей модели (пользователя, комментарии и медиа):

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

Вот примеры настройки схемы таблицы:

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

А теперь вот пример примера rspec, который я пробовал:

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

И, наконец, сообщение об ошибке, которое дает мне rspec:

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

Также обратите внимание, что это происходит для всех моих столбцов counter_cache во всех моих моделях. Я также попробовал несколько различных способов проверить это, но все они возвращают вышеуказанное сообщение об ошибке.

Очень надеюсь, что кто-то может помочь мне с этим.:)

Спасибо заранее! Люк

1 ответ

Решение

counter_cache обновляется в базе данных напрямую. Это не повлияет на копию модели, которую вы загрузили в память, поэтому вам необходимо перезагрузить ее:

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

Но я не думаю, что так я бы это проверил. Как у вас есть, ваш тест очень тесно связан с установочным кодом, который, кажется, не должен быть там вообще. Как насчет чего-то подобного для отдельной спецификации:

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

Для testng counter_cache вы можете использовать гем Shoulda-Matchers, есть метод из коробки

Другие вопросы по тегам