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

David Chelimsky dchelimsky at gmail.com
Tue Apr 17 22:43:53 EDT 2007


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.

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


More information about the rspec-users mailing list