Need to clear Mocha expectation?

Hi Folks,

I have a problem that I have been able to isolate into a small test
application.

The problem seems to be that when I set an expectation on the number of
times a method will be called in one describe block, the expectation is
still set in a different describe block. My understanding was that
RSpec restored the state of objects and the end of a test, which I
interpreted as the end of a describe block (seeing that the scope of the
expectation ended).

Here is my test application:
: rails rspecproblem
: cd rspecproblem
<install rspec & rspec-rails>
: script/generate rspec_model Contest contest_name:string status:integer
contest_series_id:integer
: script/generate rspec_model ContestSeries series_name:string
: rake db:migrate
: autotest

I edited contest.rb and set the following:
class Contest < ActiveRecord::Base
belongs_to :contest_series

def getSeries
ContestSeries.find(contest_series_id)
end
end

I edited contest_series.rb and added the has_many statement:
class ContestSeries < ActiveRecord::Base
has_many :contests
end

I then created the following spec file in spec/models/contest_spec.rb
that can be found at http://pastie.org/283936

The summary of the test spec is that there are two describe blocks. The
first block creates a Contest and assigns it to a ContestSeries. For
the sake of the example, I then call ContestSeries.find().

The second block sets an expectation on ContestSeries that the find
method will be called only once.

This causes the following error:

Mocha::ExpectationError in ‘Contest should demonstrate that the stub is
not cleared’
unexpected invocation: ContestSeries(id: integer, series_name: string,
created_at: datetime, updated_at: datetime).find(1)
satisfied expectations:

  • expected exactly once, already invoked once: ContestSeries(id:
    integer, series_name: string, created_at: datetime, updated_at:
    datetime).find(1000)

Playing around with some variations, I have found that if I change the
code in line 24 to:

ContestSeries.expects(:find).at_least(1)

then no error is generated, but this isn’t really what I want. I want
to be confident that the “getSeries” call (which is really only a
simplification of the actual code) gets the correct ContestSeries.

Have I misunderstood how to use this stubbing behavior? Is there a way
to correctly clear such expectations in an after block?

Many thanks,

Peter

On Thu, Oct 2, 2008 at 5:20 PM, Peter Degen-Portnoy
[email protected] wrote:

expectation ended).

class ContestSeries < ActiveRecord::Base

  • expected exactly once, already invoked once: ContestSeries(id:
    integer, series_name: string, created_at: datetime, updated_at:
    datetime).find(1000)

Playing around with some variations, I have found that if I change the
code in line 24 to:

ContestSeries.expects(:find).at_least(1)

You learn something new every day!

First, the fix: in spec_helper.rb

Spec::Runner.configure do |config|

config.mock_with :mocha

end

The problem is that rspec needs to know that you’re using mocha in
order for it to call the mocha methods needed to verify and reset at
the end of each example.

The reason that the examples that use mocha methods seem to recognize
those mocha methods is that, as I only just learned, rails might
automatically load mocha in the test environment (depending on a few
other factors in your system) implicitly without any direction to do
so. If you’re a mocha user, this is a good thing. Not so great if
you’re using other frameworks :slight_smile: C’est la vie.

Cheers,
David

David C. wrote:

First, the fix: in spec_helper.rb

Spec::Runner.configure do |config|

config.mock_with :mocha

end

Indeed! There was even such a line ready to be uncommented in
spec_helper.rb

Thank you so very much! That did indeed fix the problem nicely.

  • Peter