[mocha-developer] I'm misunderstanding how stubs works

James Mead jamesmead44 at gmail.com
Sat Sep 23 05:11:55 EDT 2006


On 23/09/06, Paul Butcher <paul at 82ask.com> wrote:
>
> I'm using "stubs" to test some realtime functions, to control exactly
> which
> time is returned from Time.now. I would expect the following test to pass:
>
>   def test_two_stubs
>     t = Time.now - 60
>     Time.stubs(:now).returns(t)
>
>     start_time = Time.now
>
>     t += 20
>     Time.stubs(:now).returns(t)
>
>     end_time = Time.now
>
>     assert_equal end_time - start_time, 20
>   end
>
> But it fails with:
>
>   1) Failure:
> test_two_stubs(MochaTest) [mochatest.rb:19]:
> <0.0> expected but was
> <20>.
>
> I can create a test which works as I intend:
>
>   def test_lambda
>     t = Time.now - 60
>     Time.stubs(:now).returns(lambda { t })
>
>     start_time = Time.now
>
>     t += 20
>
>     end_time = Time.now
>
>     assert_equal end_time - start_time, 20
>   end
>
> But I'd be interested to understand why the first version doesn't.
>

Hi Paul,

The first version doesn't work, because the second stub expectation doesn't
replace the first. When the end_time call to Time.now comes in, it is
matched to the first expectation and so returns the first value of t. I
agree that this is not what you would expect and it's been on my todo list
for a while. It hasn't made it to the top, because there are ways round it
as you have demonstrated. I would probably use the same technique as you,
but you might be interested to see a couple of other possibilities...

The first one makes use of the fact that expectations match based on
parameters as well as method name. Even though Time.now doesn't take any
parameters, you can supply a block which returns true or false depending on
whether it should match...

  def test_two_stubs_with_parameter_block
    t = Time.now - 60
    context = :start
    Time.stubs(:now).with { context == :start }.returns(t)
    Time.stubs(:now).with { context == :finish }.returns(t + 20)

    start_time = Time.now

    context = :finish

    end_time = Time.now

    assert_equal end_time - start_time, 20
  end

The second one makes use of a recent change in HEAD (not released in the
gem), which allows you to specify consecutive return values. Although this
won't be useful if there are many calls to Time.now...

  def test_two_stubs_consecutive_return_values
    t = Time.now - 60

    Time.stubs(:now).returns(t, t + 20)

    start_time = Time.now

    end_time = Time.now

    assert_equal end_time - start_time, 20
  end

I hope that helps.
-- 
James.
http://blog.floehopper.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://rubyforge.org/pipermail/mocha-developer/attachments/20060923/4af3a085/attachment.html 


More information about the mocha-developer mailing list