I recently integrated Warden into a web service I’ve been building with Sinatra. Unfortunately doing so completely broke some of my tests. I spent a while trying to figure out how to stub out the Warden object before I discovered that Warden already provides support for testing. Awesome. While I could load my config.ru in the test, there are other things in there that I’d rather not deal with while testing. I came up with the following approach, which lets me more or less test the web service in isolation.
require 'rack/test'
require 'sinatra'
require 'rspec'
require 'warden'
# model
class User
attr_reader :id
attr_reader :name
def initialize(name)
@id = 1 # please don't really do this
@name = name
end
end
# modular sinatra app
class Greeter < Sinatra::Base
get '/' do
"Hello, #{request.env['warden'].user.name}"
end
end
# tests
describe Greeter do
include Rack::Test::Methods
include Warden::Test::Helpers
after(:each) do
Warden.test_reset!
end
def app
Rack::Builder.new do
# these serialization methods don't do anything in this example,
# but they could be necessary depending on the app you're testing
Warden::Manager.serialize_into_session { |user| user.id }
Warden::Manager.serialize_from_session { |id| User.get(id) }
# your session middleware needs to come before warden
use Rack::Session::Cookie
use Warden::Manager
run Greeter
end
end
it 'says hi to me' do
login_as User.new('Marc')
get '/'
last_response.body.should == 'Hello, Marc'
end
end
This is basically just an inline rackup file. Where you would normally return just the Sinatra app, you instead put together the bits that you need to exercise the code under test.