Specifying dynamic gem usage with RSpec
October 31st, 2007
Between me and the helpful folk at rspec-users, I managed to come up with a solution to specify that a gem is loaded and used in a library. This is for the case where you don't want the gem loaded all the time, or where you can put the loading in a method called at some point (as opposed to just at the top of a file) - although I'm sure it could be adapted.
First is specifying that the gem is loaded. The gem and require commands are in the global namespace, because they are defined in Kernel. Specifying just require is asking for trouble, as rubygems does some meta-programming black magic on it, a bit like open-uri meddles with Kernel.open. I found the best way was to use gem, then require:
spec
1 2 3 4 5 6 |
it "should load gem 'sqlite3-ruby' then the library 'sqlite3'" do Kernel.should_receive(:gem).with("sqlite3-ruby").ordered Kernel.should_receive(:require).with("sqlite3").ordered make_new_connection end |
lib
1 2 3 |
Kernel.gem "sqlite3-ruby" Kernel.require "sqlite3" |
Next is stubbing out the modules that the gem uses. This is easy enough, the trick is to destroy them at the end so you don't get spammed with errors telling you a constant is already initialised:
spec
1 2 3 4 5 6 7 8 9 10 |
before(:each) do SQLite3 = Module.new SQLite3::Database = Class.new SQLite3::Database.stub!(:new).and_return # etc end after(:each) do Object.class_eval { remove_const :SQLite3 } end |
That's it really. It's not hard, it's just not obvious what context you have to call some of the methods in.

Sorry, comments are closed for this article.