[rspec-users] Verifying that a block calls a method

aslak hellesoy aslak.hellesoy at gmail.com
Wed Apr 18 04:18:45 EDT 2007


On 4/18/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> On 4/17/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote:
> > The only clear advise I've gotten is to
> > pass my_fun3 a stream, and let the default parameter be a STDOUT
> > stream, like so:
> >
> > def my_fun3(stream = STDOUT)
> >    [1,2,3].each { |x| stream.puts x }
> > end
> >
> >
> > Every time you use this method in production, you just leave off the
> > parameter, and it defaults to calling puts (as normal).  The stream
> > parameter is only used during testing.  This is a little disturbing,
> > because now you have to change the source to fit your tests for code
> > that will never be used in production.
>
> This is a very, very common approach in static languages - often used
> to break dependencies found in legacy (read: un-tested) code.
>
> Designing for testability is a tricky thing, for exactly the reason
> you describe. You end up designing things differently than you would
> if you didn't care about testing. The trick is finding the boundaries
> that you're comfortable with. I'm not comfortable with methods that
> are only used in tests. Parameterized methods or constructors don't
> bug me at all. They serve the tests, and impose low risk of misuse.
> That risk is lowered, in my opinion, if you use a constructor
> parameterize the constructor rather than the method.
>

A.k.a Constructor Dependency Injection (look it up) - a common
principle to aid decoupling. Very common in Java land combined with
mocks. Useful in Ruby land too.

> class MyClass
>  def initialize(io=STDOUT)
>    @io = io
>  end
>  def my_fun3
>    [1,2,3].each { |x| @io.puts x }
>  end
> end
>
> Hope that helps.
>
> David
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list