Mocha 0.3 released with Rails plugin
Posted by James Mead Thu, 24 Aug 2006 17:59:00 GMT
A new version of the Mocha mocking and stubbing library developed at Reevoo has been released.
There is now a Ruby on Rails plugin which can be installed like this…
$ script/plugin install svn://rubyforge.org/var/svn/mocha/trunkHere are the release notes…
- Rails plugin.
- Auto-verify for all expectations, including those on concrete classes.
- Include each expectation verification in the test result assertion count.
- Filter out noise from assertion backtraces.
- Point assertion backtrace to line where failing expectation was created.
- New yields method for expectations.
- Create stubs which stub all method calls.
- Mocks now respond_to? expected methods.
Thanks for patches from Chris.
Enjoy!

James,
I have spent the day trying to get a test working using your Mocha library. I have adapted the auto_mock_acceptance_test by creating a simple Rails app with a Product model and a Sale model. Product declares a “has_many” relationship with Sale and Sale declares a “belongs_to” to Product, otherwise the code is identical to what you have in the acceptance test. The problem I am unable to deal with cleanly is that the calls to the ActiveRecord API (“has_many” and “belongs_to”) are causing the auto verify to fail (Unexpected message :has_many(:sales)). How do you deal with mocking calls to class methods executed when the class under test is loaded via ‘require’? I have tried adding “product.expects(:has_many).with(:sales)” essentially after the fact (after I create a new Product), but no luck.
—Mario
I’m sorry Mario. As I mention in the README,
“AutoMocha is more experimental and is at an earlier stage of development.”
There are some issues with using AutoMocha in a Rails project, not least all the autoloading of classes that goes on. I have some potential solutions, but nothing committed to subversion yet.
Although it probably won’t get you any further, the way I get round the problem you are describing is to require the product.rb file from within setup and set up expectations on the class itself. Something like…
What are you trying to do? Have you tried using Mocha & Stubba? We are actively using these on Rails projects and they seem pretty robust. Let me know if I can help.
I can get my test to work with either Stubba or AutoMocha if I allow the tests to run piggy-backed on the Rails test_helper:
As above, the test passes successfully. However, the test is also executing all of the Rails db-interation code (because of the test_helper); Stubba intercepts the ’:sales’ call but otherwise Rails code is getting a connection to the running db and going through all the steps to interact with the MySQL backend. I would prefer to run the tests in isolation from the database so I tried removing the require that adds the ‘test_helper’ and adding any missing requires (I also turned off my db server to prove that it isn’t really being called during successful test execution) but so far all my efforts have ended in “ActiveRecord::ConnectionNotEstablished” error messages. Is it possible to run fully stubbed-out unit tests against model classes without a running database or am I missing something?
Thanks in advance for taking time to read this.
I think there might be a bit of confusion here…
Mocha & Stubba are designed to work in conjunction with each other and are known to work with Rails. However, neither of these explicitly stops all access to the database. Mocha & Stubba are designed to be used with the Rails test_helper.
AutoMocha is a different library which starts from the idea that a unit test should only test a single class. It is some way from being useable. It’s designed not to be used with the Rails test_helper. I suggest you don’t use it for now.
I suspect there are only two places in your test which are hitting the database. If you want to avoid even this very limited access to the database (which I applaud)...
1. By default, transactional fixtures are switched on which will mean that a “BEGIN” statement will be executed against the database connection and a “ROLLBACK” at the end. You can switch this off as follows…
2. ActiveRecord regularly calls the Base#columns method which results in a “SHOW FIELDS FROM products” being executed. You can stub this out as follows…
However if you want the Product attribute accessors to be available, you’ll need to return the correct array of ActiveRecord::ConnectionAdapters::Column objects.
One last thing – if you require ‘mocha’ as well as ‘stubba’ (which is what the Rails plugin does), you can simplify your test a bit…
This article might be useful in ensuring your tests never touch the database.
This article helps discriminate between when to mock and when to stub.
Hi James,
I will do some experimenting to find a way to isolate active record code from what I am trying to test in the model. Thanks for your advice above.
—Mario
Hi there, I installed the Rails plugin, but I can’t work out what this does to environment.rb.
The problem is that environment.rb includes a “require_dependency” line, which seemingly doesn’t get included anymore.
So, is environment.rb totally ignored with Mocha installed?
or is something else going wrong?
MattyJ: The Mocha plugin should not affect what gets executed in environment.rb. The plugin is loaded using the standard plugin loading during Rails::Initializer.run called from environment.rb. Amongst other things, this call evaluates the plugin’s init.rb file. If in the test environment, Mocha’s init.rb simply requires the Rails ‘test_help’ file which sets up Rails specific Test::Unit stuff and then requires the Mocha libraries.
Can you be a bit more explicit about what is going wrong? Is it a standard part of Rails environment.rb which is not working or something you have added? What specifically is going wrong e.g. do you have a stack trace?
Please leave an email address in another comment and I’ll contact you directly. Alternatively you can contact me on this mailing list.
We have a custom ‘Validations’ module, included at the end of environment.rb
It works whenever i delete the Mocha directory.
anyway, thanks for your help
MattyJ: Not sure what’s going on here – if you send me the following files, I’ll try to look into it…
and the file where your custom validation module is defined.
Can you do this via the mailing list or using something like pastie so we don’t clutter up the comments too much.
James,
This library really works nicely. One issue that comes up (from reading Topfunky’s guide to plugins,) is in testing plugins that require AR type stuff. Since your plugin is designed to work within your larger Rails framework. How do you unit test independantly of the app you are plugging into?
I just completed testing my plugin with both Stubba and Mocha. And since it does a little bit of reflection on AR models passed in, I could simulate that with stubs. I.e. the columns array just needs things like: model=mock() model.stubs(:columns).returns([stub(:primary=>true, :name=>‘id’), stub(:primar=>false, :name=>‘name’)])
This simulates just enough of AR to satisfy my plugin’s methods.
Thanks
Thanks for the positive feedback, although I’m not quite sure whether you’re asking me a question or telling me something! I think you’re telling me something.
What you say sounds fine for detailed unit testing, although I would recommend you also have at least a few integration/acceptance tests that use real AR models. This would make sure for example that you catch any changes in AR’s API which you would miss if you were only stubbing.
If you ever see that you’re getting nil.[] errors while using the Mocha gem, simply get rid of it, and use this plugin.
jps: Can you tell me more about the errors you are seeing with the gem? It would probably be best to post to the mocha mailing list at http://rubyforge.org/mailman/listinfo/mocha-developer.
TNX for perfect developer lib. It’s good :)