如何使用RSpec测试路由约束

5

给定数据库中的几个城市:

City.first.attributes => {:id => 1, :name => 'nyc'}
City.last.attributes =>  {:id => 2, :name => 'boston'}

一个像这样的路由:

match '/:city/*dest' => 'cities#do_something', :constraints => {:city => /#{City.all.map{|c| c.name}.join('|'}/}

所以约束条件应为:/nyc|boston/。

还有一个规范:

it "recognizes and generates a route for city specific paths" do
  { :put => '/bad-city/some/path' }.should route_to({:controller => "cities", :action => "do_something", :dest => 'some/path', :city => 'bad-city'})
end

我本以为会失败,但它却通过了。

同样的情况:

it "doesn't route bad city names" do
  { :put => '/some-bad-city/some/path' }.should_not be_routable
end

我原以为它会通过,但实际上它没有通过。

规范好像忽略了限制条件,因为与坏的城市相匹配的城市具有相同的行为。

这是一个已知问题吗,还是我需要做些什么?


因为这个在开发环境中可行,但在测试环境中不行,我认为问题是限制条件在启动时评估,在测试数据库中此时没有城市。所以正则表达式看起来像 //,匹配任何东西。但当我尝试将它变成一个Proc或者实现 #matches?(request) 的类时,它似乎从未被调用过。 - Matt Van Horn
2个回答

11
这种方法是可行的: 在routes.rb文件中:
match '/:city/*destination' => 'cities#myaction', :constraints => {:city => /#{City.all.map{|c|c.slug}.join('|')}/}

在规范中:
describe "routing" do
  before(:each) do
    @mock_city = mock_model(City, :id => 42, :slug => 'some-city')
    City.stub!(:find_by_slug => @mock_city, :all => [@mock_city])
    MyApp::Application.reload_routes!
  end

  it "recognizes and generates a route for city specific paths" do
    { :get => '/some-city/some/path' }.should route_to({:controller => "cities", :action => "myaction", :destination => 'some/path', :city => 'some-city'})
  end

  it "rejects city paths for cities that don't exist in the DB" do
    { :get => '/some-bad-city/some/path' }.should_not be_routable
  end
end

最后,我添加了一个观察者来在城市表发生变化时重新加载路由。

6
路由文件(routes.rb)中这样使用db find all是很糟糕的。在这种情况下,控制器或before_filter应该验证城市。 - oma

0

当您指定约束条件时,必须包括用于约束的参数:

match '/:city/*dest' => 'cities#do_something', :constraints => { :city => /nyc|boston|philly/ }

你知道的 - 在我试图简化问题时,我引入了一个打字错误。感谢你的指出。 - Matt Van Horn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接