Testing Warden-Based Sinatra Apps

2 minute read Published:

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

# modular sinatra app
class Greeter < Sinatra::Base
  get '/' do
    "Hello, #{request.env['warden'].user.name}"

# tests
describe Greeter do
  include Rack::Test::Methods
  include Warden::Test::Helpers

  after(:each) do

  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

  it 'says hi to me' do
    login_as User.new('Marc')
    get '/'
    last_response.body.should == 'Hello, Marc'

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.