1

私はTDDを初めて使用し、SinatraとSinatra-Contribの名前空間ライブラリを使用して親クラスから継承するクラスごとにURLを生成するメソッドを作成しようとしています。RSpec テストに失敗したため、先に進むことができませんでした: undefined method 'namespace'. 誰でも助けることができますか?

Gemfile:

source 'https://rubygems.org'

ruby '1.9.3'

gem 'sinatra'
gem 'sinatra-contrib'
gem 'rack'
gem 'thin'

group :development, :test do
  gem 'rspec'
  gem 'rack-test'
  gem 'ZenTest'
  gem 'autotest-growl'
  gem 'autotest-fsevent'
end

base_model.rb:

require 'sinatra'
require 'sinatra/namespace'
require 'rack'

def generate_routes_for_model(model_class, rootUrl)
    namespace rootUrl do
      get '/show' do
        "I'm the model's show route"
      end
    end
end

base_model_spec.rb

require_relative '../base_model.rb'
require 'rack/test'

set :environment, :test

class Foo
end

def app
    Sinatra::Application
end

include Rack::Test::Methods

describe 'Create Routes for test Class' do
    it "should load foo.show" do
        generate_routes_for_model(Foo, '/foo')
        get '/foo/show'
        last_response.should be_ok
    end
end

テストの結果は次のとおりです。

失敗:

  1) Create Routes for test Class should load foo.show
     Failure/Error: generate_routes_for_model(Foo, '/foo')
     NoMethodError:
       undefined method `namespace' for #<RSpec::Core::ExampleGroup::Nested_2:0x007f8571102e00>
     # ./base_model.rb:16:in `generate_routes_for_model'
     # ./spec/base_model_spec.rb:24:in `block (2 levels) in <top (required)>'
4

1 に答える 1

1

一見すると、スコープの問題のようです。namespaceSinatra 拡張のクラス メソッドですclass(これが、インスタンス メソッド内ではなく、定義内で呼び出す理由です)。

RSpec を実行すると、namespaceを継承するクラス内にいSinatra::Baseますか? 私はそうは思わない。内部で実行できるSinatra クラスを提供する必要がありnamespaceます。例えば

class Foo; end

app = Sinatra.new do
  register Sinatra::Namespace
end

def generate_routes_for_model(app_class, model_class, rootUrl)
  ['show'].each do |route|
    app_class.namespace rootUrl do
      get route do
        "I'm the model's show route"
      end
    end
  end
end

generate_routes_for_model app, Foo, "/"
app.run!

するとhttp://localhost:4567/show、「私はモデルのショールートです」と返信されます。

または、おそらくclass_evalコードを定義するために使用します。これに取り組む方法はいくつかあります。主に留意すべきことは、スコープが正しいことを確認することです。そうしないと、アプリや RSpec などがメソッドを見つけることができなくなります。

編集:

また、before統合テスト用に設定されているため、世代をブロックに移動します(基本的に、「ルートが存在する場合、世代が機能した場合、ここでメソッドをテストする必要はありません」と言っているので、パブリック API のブラック ボックス テスト - 他の名前による統合テスト:) 単体テストとなるメソッド自体をテストする場合appは、ルートが生成されたことを確認するために を調べる必要があります。

describe 'Create Routes for test Class' do
  before do
    generate_routes_for_model(Foo, '/foo')
    get '/foo/show' # this, too, is not a test but a pre-requisite for the test
  end
  it "should load foo.show" do
    last_response.should be_ok
  end
end
于 2013-10-08T20:45:51.057 に答える