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.