Trouble testing a method with loop

I’m having trouble working out how to test a method that contains a
loop. I’m new to rspec so not sure what the best way is to tackle
this.

class Company < ActiveRecord::Base

def self.sync_with_basecamp
companies = basecamp_fetch(“companies”)

companies.each do |c|
company = self.find_or_initialize_by_name_and_postcode(c.name,
c.zip)
company.county = c.state
company.city = c.city
company.save
end

end

end

I started by checking that the number of companies in my mock
companies array was saved:

it “should write all records from array to the database” do
lambda {
Company.sync_with_basecamp
}.should change(Company, :count).by(37)
end

But I’m having trouble figuring out how to check individual records. I
can pull the first record from the mock array:

it “should populate name” do
@company.first.name.should eql(“The Media Collective”)
end

But I can’t check that this has been applied to the method because
rspec doesn’t know about the save loop.

it “should populate name” do
@company.name.should eql(“The Media Collective”)
end

Would appreciate some advice on how to tackle this please from someone
more familiar with rspec than me.

On Feb 4, 2008 5:24 AM, David C. [email protected] wrote:

company = self.find_or_initialize_by_name_and_postcode(c.name, c.zip)

companies array was saved:
it “should populate name” do
@company.first.name.should eql(“The Media Collective”)
end

It depends on how clearly you want to isolate from the database. Your
first
example is going to hit the DB 37 times. I wouldn’t do that personally.
Even
if I was hitting the database I’d reduce that dataset to one or two
records.

The way I’d approach this if I were trying to isolate from the DB would
be
like this:

@company = mock_model(Company)
Company.should_receive(:basecamp_fetch).
with(“companies”).
and_return([@company])

… expectations about @company

HTH,
David

Thanks,

Point taken about less interaction with the database. The ‘companies’
mock is an exact representation of the companies list returned by the
basecamp api which is why there’s 37 records in there. I need to learn
to think more clearly about separation from the database I guess.

The point is actually that none of these examples are touching the
database at the moment because rspec doesn’t know about the
companies.each do loop in the model. I’m wanting to cycle through the
list of companies in the fetched array and save these as rows in the
database.

I have done a basic implementation of this in the model, but I can’t
get this through to rspec.

Great, thanks for that,

d.

Extract the company creation to a method, so that that method only
builds one record at a time. Test that it works properly. Then you
can keep the test that you have, verifying that it creates the right
number of records.

Pat