[rspec-users] Isolating rails model specs from their implementation

Kyle Hargraves
2007-07-29T20:16:15Z

Russell Tracey wrote:
> It''s my understanding that model specs (and specs in general)
should
> be shielded from the implementation details, so how do i check that
> Project.active_projects only returns active projects without looking
> at assuming something about the implementation? My initial thought is
> to check each of them using one of the other exposed methods above, in
> this case...
>
>   Project.active_projects.all? {|p| p.active? }
>
> but then i can''t work out how to spec all the other methods
without
> going round in circles so that each spec would end up assuming that
> the other methods work (in this case that p.active? is working) or
> worse resorting to peeking at implementation details.

Nothing is wrong with assuming that everything else works as it should.
In fact, it''s pretty much exactly what you want: you only care about
the
behaviour of the little facet of the model you''re dealing with *right
now*. If something else doesn''t work, some other spec is responsible
for
demonstrating that it''s misbehaving.

As for the specific issue, I typically do something like:

Spec that active? and archived? do what they should. Those probably
actually do require some form of implementation details -- if X column
has Y value, it''s archived, otherwise not, etc.

Then, spec archive! (and unarchive!):

   it "should archive projects" do
     @project.archive!
     project = find_that_project_again
     project.should be_archived
   end

And finally, for your finders:

   before(:each) do
     active_projects = set_up_some_active_projects
     archived_projects = set_up_some_archived_projects
   end

   it "should return only active projects" do
     all_active = Project.active_projects.all? { |p| p.active? }
     all_active.should be_true
   end

So the entirety really only hinges on active? and archived? working
properly. And if active? is just !archived?, there''s only one real spot
from which errors will start cascading.

HTH,
Kyle