简体   繁体   中英

Set Up for RSpec in a Sinatra modular app

This is my first attempt with Sinatra. I built a simple classic app, set up RSpec for it, and got it working. Then, I tried to go modular, in a MVC fashion. Even though the app works in the browser, RSpec throws a NoMethodError . I've read Sinatra docs regarding RSpec, also searched a lot here in SO, but I can't find where the bug is. Any clue?

Thank you very much in advance.

Here are my relevant files:

config.ru

require 'sinatra/base'

Dir.glob('./{app/controllers}/*.rb') { |file| require file }

map('/') { run ApplicationController }

app.rb

require 'sinatra/base'

class ZerifApp < Sinatra::Base
  # Only start the server if this file has been
  # executed directly
  run! if __FILE__ == $0
end

app/controllers/application_controller.rb

class ApplicationController < Sinatra::Base
  set :views, File.expand_path('../../views', __FILE__)
  set :public_dir, File.expand_path('../../../public', __FILE__)

  get '/' do
    erb :index
  end
end

spec/spec_helper.rb

require 'rack/test'

# Also tried this
# Rack::Builder.parse_file(File.expand_path('../../config.ru', __FILE__))

require File.expand_path '../../app.rb', __FILE__

ENV['RACK_ENV'] = 'test'

module RSpecMixin
  include Rack::Test::Methods
  def app() described_class end
end

RSpec.configure { |c| c.include RSpecMixin }

spec/app_spec.rb

require File.expand_path '../spec_helper.rb', __FILE__

describe "My Sinatra Application" do
  it "should allow accessing the home page" do
    get '/'
    expect(last_response).to be_ok
  end
end

The error

My Sinatra Application should allow accessing the home page
     Failure/Error: get '/'
     NoMethodError:
       undefined method `call' for nil:NilClass
     # ./spec/app_spec.rb:5:in `block (2 levels) in <top (required)>'

I'm guessing you're following this recipe , correct?

The described_class in this line:

def app() described_class end

is meant to be the class under test, in this case ZerifApp . Try it like so:

def app() ZerifApp end

EDIT

It turns out the above answer is not correct about what described_class does. I assumed it was a placeholder -- actually it is an RSpec method that returns the class of the implicit subject, that is to say, the thing being tested.

The recipe at the link is misleading because of the way it recommends writing the describe block:

describe "My Sinatra Application" do

This is valid RSpec, but it does not define the subject class. Executing described_class in an example for this block will return nil . To make it work, replace the describe block:

describe ZerifApp do

Now described_class will return the expected value ( ZerifApp )

https://pragprog.com/book/7web/seven-web-frameworks-in-seven-weeks

It has some source code to get some ideas from.

This has code example too. https://github.com/laser/sinatra-best-practices

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM