[rspec-users] Speccing private class methods

Ashley Moran work at ashleymoran.me.uk
Thu Dec 21 10:16:24 EST 2006

On 21 Dec 2006, at 12:59, David Chelimsky wrote:

> In theory you shouldn't be specifying anything about private methods.


Here is my original thinking:
  - I've written a method somewhere (private or otherwise) that is  
specified independently
  - I know the algorithm must use this method to behave correctly
  - therefore I should specify that the main method calls the  
auxillary one

Not testing the private methods seems to increase the granularity of  
the specs too much.  There's a lot of stuff we do has complex but  
decomposable algorithms, and it makes sense to test the parts of  
these even if they are not part of the public interface.  Not doing  
so seems similar to not unit testing ActiveRecord models because you  
can test their behaviour in the controller specs (which is what Rails  
does with Test::Unit)

> The only reason we support partial mocks at all (which is a mocking
> no-no) is because Rails forces us to.

Why is this so wrong and what about about Rails forces it?  I'm new  
to mocking and I'm not sure I'm clear on the definition.  (Does the  
following code count as partial mocking, seeing how "date" is  
required in the CapFutureResidual  model class file?)

Here is a spec I wrote today that tests a really simple (private)  

context "CapFutureResidual.registration_date_recent?" do
   setup do
     Date.stub!(:today).and_return(Date.new(2006, 12, 20))

   specify "should find the current date" do
(2006, 12, 20))
     CapFutureResidual.send(:registration_date_recent?, Date.new 
(2006, 06, 25))

   specify "should define a data under six months old (approx) as  
recent" do
     CapFutureResidual.send(:registration_date_recent?, Date.new 
(2006, 06, 23)).should == true

   specify "should define a date over six months old (approx) as not  
recent" do
     CapFutureResidual.send(:registration_date_recent?, Date.new 
(2006, 06, 22)).should == false

Again, I don't see how specifying Date.should_receive(:today) is  
different from specifying that a private method is called, or should  
I not  be doing this either...

> You won't find a solution to your problem within RSpec, but you can  
> do this:
> specify "(2) call_private_method should call private_method" do
>   begin
>     MyClass.send :public, 'private_method'
>     MyClass.should_receive(:private_method).and_return("this is  
> private")
>   ensure
>     MyClass.send :private, 'private_method'
>   end
> end
> So, for this spec only, you can access the method to spec that it gets
> called, but then restore the method to its private state.

Hmmm... not sure if I'd like to write specs like this... might just  
drop that spec entirely and include the behaviour of the private  
method in the spec for the calling method.


More information about the rspec-users mailing list