[rspec-users] Specing protected methods

David Chelimsky dchelimsky at gmail.com
Thu Oct 23 09:51:53 EDT 2008


On Thu, Oct 23, 2008 at 6:49 AM, Bastien <bastien.vaucher at gmail.com> wrote:
> I totally agree with the ''listening to your specs" concepts and
> always divide my code into small methods easier to spec.
> Now let me get you right, here's my code :
>
> class Survey < ActiveRecord::Base
>  has_many :participants
>  ...
>  def generate_reports
>    ...
>    sub_total = sub_total(participants.reports)
>    ...
>  end
>
> protected
>
>  def sub_total(reports)
>    sub_total = 0
>    reports.collect do |report|
>      sub_total = sub_total + report.score
>    end
>   return sub_total
>  end
>
> end
>
> I m already specing the "generate_reports" methods with a mock on
> "sub_total", but I would also like to spec that method. I've put this
> method into protected because it doesn't make sens to call it from
> outside this class. But you're arguing that I should put that method
> into a lib ? I m not sure it would make sense as this method is very
> specific to that class, and would actually be easy to spec. Except
> that it's not possible to call a protected method from a spec as far
> as I know, correct me if I m wrong. (I maybe didn't explain my problem
> well in the first place)

This sort of decision is always a balancing act. Leaving it where it
is means you have to either

* unprotect it, which you clearly prefer not to do
* expose it for you code example using clever ruby trickery
* give up testing it directly
* move it to another class, adding conceptual weight to your system

None of these are perfect and all come with some tradeoff.

I'll confess that, in practice, I'd probably not test this directly.
More often than not, for me, the sub_total method is a result of
refactoring the generate_reports method, which by that time would have
at least two code examples in which the only difference is the sum of
scores of the reports.

In this case, however, assuming participants and reports are AR backed
models, you don't really need to introduce a new class:

subtotal = participants.reports.sum('score')

Cheers,
David




>
> Regards
>
> -- Bastien
>
> On Oct 23, 12:37 pm, Matt Wynne <m... at mattwynne.net> wrote:
>> On 23 Oct 2008, at 10:16, Bastien wrote:
>>
>> > Hi everyone,
>> > Do anyone know if there's a way to spec protected methods ?
>> > Thanks in advance
>>
>> Sorry if this sounds preachy, but I would always advise you to factor
>> out the code in the method into another class, then test that class.
>>
>> If the behaviour of the method is so complex you need to test it on
>> it's own, it deserves to be in a class all by itself.
>>
>> This is what we call, 'listening to your specs' - if it's hard to
>> spec, you've probably got the design wrong.
>>
>> HTH,
>> Matt
>> _______________________________________________
>> rspec-users mailing list
>> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list