[rspec-users] We can't 100% remove our unit tests from the database, can we?

aslak hellesoy aslak.hellesoy at gmail.com
Thu Feb 22 16:42:14 EST 2007

On 2/22/07, Pat Maddox <pergesu at gmail.com> wrote:
> I hope this isn't too rambly.  This is sort of a brain dump of a
> subject I've been thinking about for months as I've used RSpec.
> Let's say we've got a simple query method, that will find all the
> users in the DB older than 18.  Our model could look like
> class User < ActiveRecord::Base
>   def self.find_older_than(age)
>     find :all, :conditions => ["age > ?", age]
>   end
> end
> What would our spec look like?
> specify "should find all users over the given age" do
>   User.should_receive(:find).with(:all, :conditions => ["age > ?", 18])
>   User.find_older_than 18
> end
> I don't know about you, but to me that sucks.  There is no TDD rhythm
> there.  We write a failing spec, but it's a fairly complex spec.  On
> top of that we've basically implemented the method from within the
> spec.  That's not TDD.
> We also can't refactor.  Let's say that at some point we decided to
> change the method to
> def User.find_older_than(age)
>   find(:all).select {|u| u.age > age }
> end
> Our spec would break, even though the semantics of
> User.find_older_than hasn't changed.
> Okay, so it's just a crappy spec.  But how do we change it?  Lots of
> people suggest stubbing out DB calls.  There's no sense in testing the
> same thing over and over - namely that you have a connection and your
> ORM tool is working correctly.
> I'm beginning to think that most of the time, you don't want to use a
> test DB at all.  When you're testing an AR model, just use an
> in-memory record and stub any associations you need.  But when you do
> do something that interacts with the database - like doing a custom
> find - you need to use the database to make sure that you're getting
> the right results.  Whether you use fixtures or create some records in
> the setup method, you have to actually hit the db.
> Let me know what you think.  I'm completely open to the idea that I've
> missed something pathetically obvious.

Only mock AR when you're speccing code that *interacts* with AR
(controllers and views).

Don't mock AR in specs for AR subclasses - let them go against a real database.

Don't mock APIs you don't own.
See http://www.jmock.org/oopsla2004.pdf for more on this


> Pat
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

More information about the rspec-users mailing list