7

几天来,我一直在努力找出应该很容易做到的接缝的底部……但是,我对 rails 和 ruby​​ 的世界还是很陌生,我只是无法解决这个问题。 .. :p

无论如何,我遇到的问题是我的模型中有许多 :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 列中。我也尝试了许多不同的测试方法,但它们都返回了上述错误消息。

真的希望有人可以帮助我解决这个问题。:)

提前致谢!卢克

更新:这会以同样的方式影响 counter_culture,下面的解决方案也解决了 counter_culture 的问题。

4

2 回答 2

29

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
于 2012-08-29T05:16:52.307 回答
0

对于 testng counter_cache,您可以使用 Shoulda-Matchers gem,有开箱即用的方法

于 2020-09-09T07:24:33.937 回答