1

我是 TDD 的新手,我正在尝试编写方法来生成基于每个类的 URL,这些 URL 使用 Sinatra 和 Sinatra-Contrib 中的命名空间库从父类继承。我并没有走得太远,因为我的 RSpec 测试失败了,这让我无法继续前进:未定义的方法“命名空间”。任何人都可以帮忙吗?

宝石文件:

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?我不这么认为。您需要提供一个namespace可以在其中运行的 Sinatra 类。例如

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 回答