Reputation: 1473
I am trying to get a Bill object to perform tests on. This is a US congress bill, which I have in xml via rsync on a data directory. My code takes in the name of the bill, say "h1.xml", parses the xml and then gets the full text of the bill from www.govtrack.us. So, in my main app, to create a bill
def self.update_from_directory Dir.glob("#{Rails.root}/data/bills/small_set/*.xml").each do |bill_path| bill_name = bill_path.match(/.*\/(.*).xml$/)[1] b = Bill.find_or_create_by(:govtrack_name => bill_name) b.update_bill b.save! end end
def update_bill file_data = File.new("#{Rails.root}/data/bills/#{self.govtrack_name}.xml", 'r') bill = Feedzirra::Parser::GovTrackBill.parse(file_data) if bill && (self.introduced_date.nil? || (bill.introduced_date.to_date > self.introduced_date)) self.congress = bill.congress self.bill_type = bill.bill_type self.bill_number = bill.bill_number ... and so on . . . until: get_bill_text
def get_bill_text bill_object = HTTParty.get("#{GOVTRACK_URL}data/us/bills.text/#{self.congress.to_s}/#{self.bill_type}/#{self.bill_type + self.bill_number.to_s}.html") self.bill_html = bill_object.response.body self.text_updated_on = Date.today Rails.logger.info "Updated Bill Text for #{self.ident}" end
My goal is very simple, I want to mock a whole bill for a test:
def setup @my_test_bill = Bill.new(:govtrack_id => "h1") @my_test_bill.update_bill end
I am trying to get webmock and vcr working, but all the examples I can find, provide a way to mock a specific call and I don't want to have to retype a whole new update_bill method.
Any thoughts greatly appreciated.
Tim
Upvotes: 0
Views: 182
Reputation: 26
Consider changing your update_bill method to:
def update_bill
file_data = File.new("#{Rails.root}/data/bills/#{self.govtrack_name}.xml", 'r')
bill = Feedzirra::Parser::GovTrackBill.parse(file_data)
if bill && (self.introduced_date.nil? || (bill.introduced_date.to_date > self.introduced_date))
self.congress = bill.congress
self.bill_type = bill.bill_type
self.bill_number = bill.bill_number
# Yield to a block that can perform arbitrary calls on this bill
if block_given?
yield(self)
end
# Fill bill text if empty
if bill_html.blank? && text_updated_on.blank?
get_bill_text
end
end
Then change your setup method to:
def setup
@my_test_bill = Bill.new(:govtrack_id => "h1")
@my_test_bill.update_bill do |bill|
bill.text_updated_on = Date.today
bill.bill_html = "The mock bill contents"
end
end
That may not be exactly the solution, but this kind of approach--passing the receiver back to a block given to the method, allows you to modify the exact behavior of a given method at runtime.
Upvotes: 1