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

Pat Maddox pergesu at gmail.com
Thu Feb 22 15:41:35 EST 2007

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]

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

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 }

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.


More information about the rspec-users mailing list