rspec questions: same file? mocks objects as params?

D

David Weldon

I'm just getting started with rspec. Two questions:

1) Should the rspec be in the same file as the production code? The
examples on the rspec site seem to indicate they should be in a separate
file but I wanted to double check.

2) If I use mocks, am I supposed to pass them as parameters to my
production code?

If my code looked like:

def read()
db = database.instance()
db.execute(....)
end

and I want to do a mock database connection do I have to write the
production code like:

def read(db=database.instance())
db.execute(....)
end

and then call it with read(my_mock) ?
 
P

Pat Maddox

I'm just getting started with rspec. Two questions:

1) Should the rspec be in the same file as the production code? The
examples on the rspec site seem to indicate they should be in a separate
file but I wanted to double check.

Specs should be separate. In a Rails app there's a spec dir that
parallels your app dir. If you're writing a Ruby app from scratch
then you'll need to create it yourself. But definitely stick specs in
separate files from production code.

2) If I use mocks, am I supposed to pass them as parameters to my
production code?

If my code looked like:

def read()
db = database.instance()
db.execute(....)
end

and I want to do a mock database connection do I have to write the
production code like:

def read(db=database.instance())
db.execute(....)
end

and then call it with read(my_mock) ?

You can do it that way, or you can stub the call to #instance and have
it return the mock.

Also, without knowing anything about your code :) I would be more
likely to pass the datastore into the constructor:

class Person
def initialize(datastore)
@datastore = datastore
end

def read
conn = @datastore.instance
conn.execute(...)
end
end

Then your spec would look something like:

describe Person, " reading a record" do
before:)each) do
@mock_connection = mock("db connection")
@mock_pool = stub("connection pool", :instance => @mock_connection)

@person = Person.new @mock_pool
end

it "should get a connection" do
@mock_pool.should_receive:)instance).and_return @mock_connection
@person.read
end

it "should select data from the database" do
@mock_connection.should_receive:)execute).with(...)
@person.read
end
end

Which is sort of ugly because you have a mock returning a mock, but
such is life with a singleton :)

Pat
 
G

Giles Bowkett

2) If I use mocks, am I supposed to pass them as parameters to my
production code?

If I understand correctly you shouldn't change your production code at
all. The goal of mocks, basically, is that they enable you to cleanly
separate the specs from the production code. With the example stuff
Pat wrote, you get that. You want to set up the mocks to parallel
whatever is happening in the production code that you don't actually
want run by the specs - hitting the database is part of that because
the DB gives you a bottleneck and speed really matters when it comes
to tests (you'll only actually use the tests (or specs) if they're
fast). But the point is you shouldn't change production code to do
anything with a mock. The whole point of a mock is that it allows your
tests or specs to run as if the production code was behaving as
normal.

--
Giles Bowkett

Podcast: http://hollywoodgrit.blogspot.com
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com
 
P

Pat Maddox

If I understand correctly you shouldn't change your production code at all.

Well, not quite. If you're retrofitting tests onto existing code,
you'll often need to change the production code to work with mocks.
That's because most code that isn't written with testability in mind
tends to be too coupled, because it's just easier to write code that
way. So you certainly could have to break those dependencies when
you're writing tests after the fact.

But you're right, the whole point of mocks is to allow you to swap in
a different object with the same interface. Mocking isn't a silver
bullet of course...code that's easy to mock isn't necessarily
well-design, but in general there are fewer dependencies - a Good
Thing.

Pat
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,667
Latest member
DaniloB294

Latest Threads

Top