[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.
Hmmm...
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)
method:
context "CapFutureResidual.registration_date_recent?" do
setup do
Date.stub!(:today).and_return(Date.new(2006, 12, 20))
end
specify "should find the current date" do
Date.should_receive(:today).with(:no_args).and_return(Date.new
(2006, 12, 20))
CapFutureResidual.send(:registration_date_recent?, Date.new
(2006, 06, 25))
end
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
end
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
end
end
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.
Ashley
More information about the rspec-users
mailing list