2011-06-12 71 views
20

我使用Test :: Unit测试我的Rails应用程序。我经常碰到的问题是测试我的应用程序的路线,但我还没有找到解决方案。在Rails 3中测试子域约束路由

目前,我正在研究使用Basecamp风格子域名来区分帐户的应用程序。

有其需要的子域

constraints(SubdomainRoute) do 
    get "/login" => "user_sessions#new", :as => :login 
    get "/logout" => "user_sessions#destroy", :as => :logout 
    ... 
end 

只能没有一个子域被访问

constraints(NoSubdomainRoute) do 
    match "/" => "public#index", :as => :public_root 
    match "/signup" => "public#signup", :as => :signup 
    ... 
end 

类SubdomainRoute被定义为路线以及路线:

class SubdomainRoute 
    def self.matches?(request) 
    request.subdomain.present? && request.subdomain != "api" && request.subdomain != "www" 
    end 
end 

NoSubdomainRoute类正好相反。

路由按预期工作,但我如何测试那些使用Test :: Unit?

在功能测试,我可以这样做

assert_routing "/signup", :controller => "public", :action => "signup" 

,但我不能提供一个子域,所以实际上是唯一的测试Rails内部它增加什么可测试我的应用程序。在这种情况下,我想测试的是使用或不使用子域时可以访问signup_path/signup_url。

在代码中,这样的事情

assert_raise(ActionDispatch::RoutingError) { get "http://account.test.host/signup" } 
get "http://www.test.host/signup" 
assert_response :success 

GET在这种情况下,因为测试::单位把整个URL作为控制器的动作(...不起作用:动作=>“HTTP:// account.test.host/signup“)。

设置

@request.host = "subdomain.test.host" 

只有在你内心的控制器代码的影响(例如,通过提取主机子域获得活期账户),但并不影响在这种情况下,路由。

我不知道集成测试中的情况是否有任何不同。

所以这两个主要问题是

  1. 意味着路由进行一般testet?
  2. 如何他们测试关于这种特殊情况?

我williing尝试不同的方法(水豚和朋友),但我不希望我的切换测试框架(已经有了我的RSpec的时间),因为我,否则很高兴与测试::单元。

在此先感谢和亲切的问候!

回答

0

我为自己新的@ RoR3但也许这截屏将帮助您:Railscasts Subdomain

+1

感谢您的回复,但我的子域名已在使用 - 我的许多功能源于Ryan,但不幸的是,在此屏幕录像中,他没有关于测试的任何单词。 – 2011-06-18 09:18:24

0

我会测试你的类的功能不一定是路由本身。我觉得这本质上是测试轨道。

你知道,如果你通过类来约束,如果你已经定义了.matches阻止它是否行得通呢?方法。所以只要测试一下你在那里得到预期的逻辑。

0

马特丹波利托上面所说的,测试要发生什么。

在你的限制,你必须有某种的before_filter或某事的,处理时有人不应该是他们在哪里的情况。或者甚至像www.yourdomain.com/login一样,您必须使用重定向和闪烁警告来处理这种情况,以便您可以对此进行测试。

甚至还在,在我来说,我的子域,给我分配与子域邮件的变量。这是我在我的测试中检查的变量,如:

setup do 
    # get_sub is just @request.host = "#{sub}.local.me" in test_helper.rb 
    get_sub("two") 
    @deal = deals(:two) 
end 
test "should get show" do 
    get :show, :token => @deal.token 
    assert_response :success 
    ["deal", "subdomain", "user_profile"].each do |variable| 
    assert assigns[variable.to_sym], "I can't find a var called #{variable}" 
    end 
end 

因此测试,无论我想要的工作,并通过子。在你的情况下,它应该只是/登录响应:成功,我想。

-3

子域轨道3是非常简单,它只是推杆为:

constraints :subdomain => subdomain_name do 
    #here comes all routes which routes under above subdomain 
end 
+1

OP询问如何测试子域名,而不是创建它们。 – Galaxy 2012-02-24 09:36:53

2

我发现rr是测试子域和自定义域的最佳途径。例如,我有一个机架应用程序来操纵自定义域。下面是一个简单的测试:

require File.join(File.dirname(__FILE__), '..', 'test_helper') 
require 'rr' 
require 'custom_domain' 
require 'rack/test' 

class CustomDomainTest < ActiveSupport::TestCase 
    include Rack::Test::Methods 
    include RR::Adapters::TestUnit 

    def app 
    Rails.application 
    end 

    def test_cname_to_subdomain 
    mock(CustomDomain::Cname).resolver('www.example.com', '.lvh.me') { 'subdomain.lvh.me' } 
    get 'http://www.example.com:80/users' 
    assert_equal 'www.example.com, subdomain.lvh.me:80', last_request.env['HTTP_X_FORWARDED_HOST'] 
    assert_equal 'www.example.com', last_request.env['SERVER_NAME'] 
    assert_equal 'www.example.com', last_request.env['X_CUSTOM_CNAME'] 
    assert_equal 'subdomain.lvh.me', last_request.env['X_CUSTOM_SUBDOMAIN'] 

    end 
end 
end 

这里是讨论这个话题的几个环节可能对您有用:

好运。

2

我找了非可怕的方式来修补到路径测试机器没有发现任何。

我结束了刚刚删空约束比赛?方法:

describe ThingsController do 

    shared_examples_for "a subdomain route" do |http_method, path, expected_action| 
    context("on a subdomain") do 
     before do 
     stub(SubdomainRoute).matches? { true } 
     stub(NoSubdomainRoute).matches? { false } 
     end 
     it { should route(http_method, path).to(:action => expected_action) } 
    end 

    context("on the main domain") do 
     before do 
     stub(SubdomainRoute).matches? { false } 
     stub(NoSubdomainRoute).matches? { true } 
     end 
     it { should_not route(http_method, path).to(:action => expected_action) } 
    end 
    end 

    it_should_behave_like "a subdomain route", :get, '/things/new', :new 

... 

(我使用的RSpec和RR我喜欢把路线测试在我的控制器的规格,就在描述块动作共享的例子将被移动到混合到控制器模块。眼镜。)

13

其实解决的方法很简单,因为assert_routing确实支持URL:

assert_routing "http://subdomain.example.com/login", 
    { :controller => "user_sessions", :action => "new" } 

assert_routing "http://www.example.com/signup", 
    { :controller => "public", :action => "signup" } 

提供的URL assert_routing加入here的能力。

检索策略:

  • 发现assert_routingactionpack
  • gem install gemedit
  • gem edit actionpack
  • 开业lib/action_dispatch/testing/assertions/routing.rb定义,发现recognized_request_for是什么处理的路径处理
  • 通过GitHub上打开的文件,并选择'责备'来查看哪个提交添加了该功能ionality
+0

您如何指定方法,例如补丁? – 2015-03-06 17:19:17

1

为了使我的制约发展的模式下运行,我一个值添加到ENV散列,开始像这样的服务器:

site=trivial.ly ruby script/rails server 

在这里,我通过整个域,你可以改为传递子域名。然后在我的约束I类检测是域名,或ENV [:现场]值,就像这样:

class DomainConstraint 
    def initialize(domain) 
    @domains = [domain].flatten 
    end 

    def matches?(request) 
    @domains.include?(request.domain) || @domains.include?(ENV["site"]) 
    end 
end 

测试与特定的约束控制器现在是简单的设置正确的ENV [的问题:网站]值像这样(在测试::单位在这里):

require 'test_helper' 

class TrivialLy::SplashPagesControllerTest < ActionController::TestCase 
    test "should get android splash page" do 
    ENV["site"] = "trivial.ly" 
    get :android 
    assert_response :success 
    end 
end 

这适用于域约束上,它会工作同样出色的子域的约束。

1

这些其他答案都没有回答这个问题,至少没有任何优雅的方式。嘲笑是不需要的。

用Rails 3只域限制在Rails集成测试:简单地包括域在集成测试请求的一部分:

get "http://admin.example.com/dashboard" 

我测试了这个成功的(几乎)以下航线,没有问题:

scope :admin, as: 'admin', module: 'admin' do 
    constraints subdomain: 'admin' do 
    resource 'dashboard', controller: 'dashboard' 
    end 
end 

也许提问者没有使用集成测试或者老版本的Rails。