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.