I'm trying to test the Hour model with RSpec, namely the class method 'find_days_with_no_hours' that behaves like a scope. Business has_many Hours associated through STI. find_days_with_no_hours needs to be called through a Business object and I can't figure out how to set this up in the RSpec test. I want to be able to test something like:
bh = @business.hours.find_days_with_no_hours
bh.length.should == 2
I've tried various approaches, like creating a Business object (with, say, Business.create), then setting @business.hours << mock_model(BusinessHour, ..., ..., ...) but that doesn't work.
How is this normally done?
class Business < ActiveRecord::Base
has_many :hours, :as => :hourable
end
class Hour < ActiveRecord::Base
belongs_to :hourable, :polymorphic => true
def self.find_d开发者_运维知识库ays_with_no_hours
where("start_time IS NULL")
end
end
You can't test an arel method by creating the object via mocks. Arel is going to go straight into the database, and not see any mocks or anything that you've created in memory. I would grab factory_girl and then define an hour factory for yourself:
Factory.define :hour do |f|
f.start_time {Time.now}
end
Factory.define :unstarted_day, :parent => :hour do |f|
f.start_time nil
end
And then in your test...
business = Factory.create(:business)
business.hours << Factory.create(:unstarted_day)
bh = business.hours.find_days_with_no_hours
bh.length.should == 1
However, factory_girl is just a personal preference for setting up known state, you can just as easily use create
statements or fixtures, the problem for you was trying to use mock_model() (which prevents a database hit), and then using a method that queries the database.
精彩评论