Testing Sinatra application methods in isolation with RSpec

Sometimes you may want to test some Sinatra app methods in isolation (outside of a standard request flow). You probably even tried to do something like this:

require 'spec_helper'

describe App do
  subject { App.new }

  it 'expect run some specs here'
    expect(subject.current_user).to eq user
  end
end

Unfortunately you will end up with error like this:

NoMethodError: undefined method `current_user' for #<App app_file="/home/something/app.rb">
from (irb):2
from /home/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'

This will occur, because Sinatra’s App new method creates a Sinatra::Wrapper, not an App instance. Of course everything will work as it should, if you follow the get/post/put/delete way of testing Sinatra apps:

require 'spec_helper'

describe App do
  before { get '/api/v1/credit_cards.json' }
    
  it { expect(last_response).to be_ok }
end

but it will fail when trying to invoke any App methods directly.

Luckily there’s a really simple solution to this issue. You just need to initialize it by manually allocating space and “bypassing” the new method:

require 'spec_helper'

describe App do
  subject do
    app = described_class.allocate
    app.send :initialize
    app
  end

  describe '#current_user' do
    before do
      expect(subject)
        .to receive(:params)
        .and_return(params)
        .at_least(:once)
    end

    context 'when there is no user_id' do
      let(:params) { {} }

      it { expect(subject.send :current_user).to be_nil }
    end
  end
end

That way you can get the “real” app instance (not a wrapper) that you can use as a subject in your specs. That way you can test your Sinatra app methods in isolation – without having to call a full request.

29
Jun 2014
POSTED BY
POSTED IN Ruby Software
DISCUSSION 1 Comment

One Response to : Testing Sinatra application methods in isolation with RSpec

  1. Instead of

    app = described_class.allocate
    app.send :initialize

    You should be able to use

    app = described_class.new!

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>