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.

Leave a Reply