17

I have been following the 15 TDD steps to create a Rails application guide - but have run into an issue I cannot seem to resolve. For the functional test of the WordsController, I have the following code:

class WordsControllerTest < ActionController::TestCase
  
  test "should get learn" do
    get 'learn'
    assert_response :success
  end

  test "learn passes a random word" do    
    some_word = Word.new
    Word.expects(:random).returns(some_word)
    get 'learn'
    assert_equal some_word, assigns('word')
  end
end

In the Word class I have the following code:

class Word < ActiveRecord::Base
  def self.random
    all = Word.find :all
    all[rand(all.size)]
  end
end

When I run the tests, I experience the following error (shortened for brevity):

1) Failure: unexpected invocation: Word(...).random() satisfied expectations:
- expected exactly once, already invoked once: Word(...).random()

I have tried changing changing the order of the tests along with a multitude of other things, but time and time again I continue to receive the same test failure - that Word.random() has already been invoked.

I'm running Rails 3.0 beta 4 and Mocha 0.9.8. I've searched long and hard for a solution to my problem, but I can't seem to find it. I'm new to Ruby/Rails so am rather unfamiliar with the language and the frameworks.

Thanks in advance!

Vega
  • 27,856
  • 27
  • 95
  • 103
MunkiPhD
  • 3,636
  • 1
  • 29
  • 51

5 Answers5

20

mocha needs to be loaded last. I struggled a lot with this problem too.

#Gemfile
  group :test
    gem 'mocha', '~>0.9.8', :require => false
    ...
  end

and

test_helper.rb
  ....
  #at the very bottom
  require 'mocha'
oma
  • 38,642
  • 11
  • 71
  • 99
  • Exactly what I needed too. I was tearing my hair out with this for hours! Thanks! :) – John Gallagher Sep 30 '11 at 10:59
  • +1, with migration to bundler i'v messed order of mocha loading – Stanislav O. Pogrebnyak Jan 19 '12 at 11:26
  • I use Sinatra where should I include that? spec_helper.rb? but I still have that problem. – toy Feb 10 '12 at 01:50
  • As a newbie in Ruby/Rails coming from Java/Python, I struggled for the last hour with this one - had to debug for some time until I understood that mocha's test verify was only called if something from the mock was called (because the automatic call from the end requires the late binding), THANKS, THANKS, THANKS! – chesterbr May 24 '12 at 19:13
7

I had the same problem, mocked functionality was not isolated to a test, it seems to be a problem with the load order of Mocha.

I had some issues getting Mocha to work with Rails3. I found a few stackoverflow posts regarding, but didn't stumble across the solution until I found a post on agoragames.com

Basically, in the Gemfile of your project, the require for Mocha should look like:

gem 'mocha', :require => false

Then in test/test_helper.rb, add a require line for mocha:

...
...
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'mocha'

class ActiveSupport::TestCase
...
...

I think the require line for mocha in the Gemfile means that you need to already have mocha installed as a gem, bundler won't take care of it for you.

Community
  • 1
  • 1
Daniel Bower
  • 739
  • 1
  • 7
  • 27
2

How are you requiring mocha? Are you using bundler? It sounds a bit as if the mocha teardown hook isn't being called?

James Mead
  • 3,472
  • 19
  • 17
  • Is teardown supposed to be called between tests? – pushmatrix Oct 26 '10 at 00:59
  • 1
    If `Mocha` has been loaded correctly, it will have monkey-patched the test framework to call `Mocha::API#mocha_verify` & `Mocha::API#mocha_teardown` i.e. you shouldn't need to explicitly call them. The reason I was asking how `Mocha` was being required, was to work out whether things are being loaded in the correct order, so that the monkey-patching works correctly. – James Mead Oct 28 '10 at 10:55
  • 1
    If you set `MOCHA_OPTIONS=debug` as an environment variable when you run your tests, you will see which test frameworks are being successfully monkey-patched. If you are still having problems with this, let me know what the debug output is and tell me what version of Mocha you are using. Thanks. – James Mead Dec 04 '10 at 17:36
0

Those solutions didn't work for me on their own, using Ruby 2.2.2, Rails 4.2.2, mocha 1.1.0, shoulda-context 1.2.1, factory_girl_rails 4.5.0 and a few more testing related gems.

What did it was also moving these two lines at the bottom of my test_helper.rb:

require 'mocha/setup'
require 'mocha/test_unit'

I also removed require 'test/unit'. It appears that mocha/test_unit already does that for me.

Velizar Hristov
  • 662
  • 2
  • 10
  • 23
0

Additionally, it seems mocha_teardown is not being called with rails31. Mocks that are setup are never removed... (this additional hack fixes it)

  class ActiveSupport::TestCase
    def teardown
      super
      Mocha::Mockery.instance.teardown
      Mocha::Mockery.reset_instance    
    end
  end
marcusb
  • 612
  • 5
  • 11