Mocking is a great part of RSpec, and from the documentation it looks insanely easy. What had me frustrated on a current project is the fact that the mocks and stubs wouldn't always do what I'd expect them to do. No errors when methods weren't invoked, and, the worst part, mocks wouldn't be cleaned up between examples which resulted in rather weird errors. They only occurred when run as a whole with rake spec but not when I ran the specs through TextMate.

I was going insane, because noone on the mailing list seemed to have any problems, same for friends working with RSpec. Then I had another look at the RSpec configuration.

Turns out, the reason for all of this is that Mocha was used for mocking. Switching the configuration back to use RSpec's internal mocking implementation, everything worked like a charme from then on.

So what you want to have in your SpecHelper isn't this:

Spec::Runner.configure do |config|
  config.mock_with :mocha
end

but rather

Spec::Runner.configure do |config|
  config.mock_with :rspec
end

or no mention at all of mock_with which will result in the default implementation being used which is, you guessed it, RSpec's own.

Friday's tab sweep for a little weekend reading.

Tags: links, rails, ruby

When using CruiseControl.rb for continuous integration, and RSpec for testing, the defaults of CruiseControl.rb don't play that nice with RSpec. However, that can be remedied pretty simply.

By default CruiseControl.rb runs its own set of Rake task, which invoke a couple of Rails' tasks, including db:test:purge, db:migrate and test. You do want the first ones, but you'd rather have CruiseControl.rb run your specs instead of your the (most likely non-existing) Test::Unit tests.

Before running its default tasks it checks whether you have a specific task configured in your project settings, and if you have a task called cruise in your project's Rakefiles. You can use both, but I just declared a task cruise in the Rakefile, and I was good to go.

That task can to pretty much the same as the original CruiseControl.rb implementation, and even be shorter since it can be tailored for your project, but invokes spec instead of test. One caveat is to set the correct environment before running db:migrate. I split out a tiny prepare task which does just that, and can do a couple of other things, if necessary, like copying a testing version of your database.yml.

desc "Task to do some preparations for CruiseControl"
task :prepare do
  RAILS_ENV = 'test'
end

desc "Task for CruiseControl.rb"
task :cruise => [:prepare, "db:migrate", "spec"] do
end

Simple like that. The task spec will automatically invoke db:test:purge, so you don't need that.