[rspec-users] Specing protected methods

David Chelimsky dchelimsky at gmail.com
Thu Oct 23 11:33:17 EDT 2008


On Thu, Oct 23, 2008 at 10:00 AM, Bastien <bastien.vaucher at gmail.com> wrote:
> Thanks for all your answers.
>
> I was just wondering how about using send in my specs ? It would
> bypass the protected limitation without altering my code :
>
> @survey.send( :sub_total, [@mock_report] )
>
> Is that the kind of trickery you were referring to David ? Would that
> be bad practice ?

If you're going to do this, use __send__ or your code examples will
break if/when you go to Ruby >= 1.9.

As for good/bad practice, here's the way I see it: there is a lot of
evidence that encapsulation is a good thing in that it constrains
contact points between objects, making them less coupled and easier to
modify internally, swap in and out (polymorphism), etc, etc.

Every time you violate encapsulation by using __send__, even in code
examples, you increase coupling by a little bit, and make your system
that much more brittle. So while one violation might seem harmless,
it's a slippery slope (sorry for the cliché).

With all that - you'll find __send__ in my code, and in my code
examples. But I'm conscious of the risks. FWIW.

Cheers,
David

>
> Regards
>
> -- Bastien
>
> On Oct 23, 3:51 pm, "David Chelimsky" <dchelim... at gmail.com> wrote:
>> On Thu, Oct 23, 2008 at 6:49 AM, Bastien <bastien.vauc... 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-us... at rubyforge.org
>> >http://rubyforge.org/mailman/listinfo/rspec-users
>>
>> _______________________________________________
>> 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