我正在用Test :: Unit测试我的Rails应用程序.我经常遇到的一个问题是测试我的应用程序的路线,但我还没有找到解决方案.
目前,我正在开发一个使用Basecamp风格子域来区分帐户的应用程序.
有些路由需要子域
constraints(SubdomainRoute) do
get "/login" => "user_sessions#new", :as => :login
get "/logout" => "user_sessions#destroy", :as => :logout
...
end
Run Code Online (Sandbox Code Playgroud)
以及只能在没有子域的情况下访问的路由
constraints(NoSubdomainRoute) do
match "/" => "public#index", :as => :public_root
match "/signup" => "public#signup", :as => :signup
...
end
Run Code Online (Sandbox Code Playgroud)
SubdomainRoute类定义为:
class SubdomainRoute
def self.matches?(request)
request.subdomain.present? && request.subdomain != "api" && request.subdomain != "www"
end
end
Run Code Online (Sandbox Code Playgroud)
NoSubdomainRoute类恰恰相反.
路由按预期工作,但如何使用Test :: Unit测试?
在功能测试中,我可以做类似的事情
assert_routing "/signup", :controller => "public", :action => "signup"
Run Code Online (Sandbox Code Playgroud)
但我无法提供子域,所以实际上只测试Rails内部,这对测试我的应用程序没有任何帮助.在这种情况下我想要测试的是,无论有没有子域,都可以访问signup_path/signup_url.
在代码中,这样的东西
assert_raise(ActionDispatch::RoutingError) { get "http://account.test.host/signup" }
get "http://www.test.host/signup" …Run Code Online (Sandbox Code Playgroud) 这个问题似乎是一个重复的这一个,但接受的答案并不与我的问题有所帮助.
上下文
由于Rails 5不再支持在控制器测试中直接操作会话(现在继承自ActionDispatch :: IntegrationTest),因此我将走向模拟和存根的黑暗道路.
我知道这是不好的做法,并且有更好的方法来测试控制器(我确实理解他们转向集成测试)但我不想运行完整的集成测试并在单个测试中调用多个动作来设置特定的会话变量.
脚本
使用Mocha模拟/存储会话变量实际上非常简单:
ActionDispatch::Request::Session.any_instance.stubs(:[]).with(:some_variable).returns("some value")
Run Code Online (Sandbox Code Playgroud)
问题是,Rails 在会话中存储了很多东西(只是session.inspect在你的一个视图中的任何地方执行),并且对该:[]方法进行存根显然会阻止对其中任何一个的访问(因此session[:some_other_variable]在测试中将不再起作用).
这个问题
有没有办法:[]在使用特定参数调用时保留/模拟方法,并保留所有其他调用未被删除?
我希望有类似的东西
ActionDispatch::Request::Session.any_instance.stubs(:[]).with(:some_variable).returns("some value")
ActionDispatch::Request::Session.any_instance.stubs(:[]).with(anything).returns(original_value)
Run Code Online (Sandbox Code Playgroud)
但我找不到办法让它完成.
有没有办法使用脚本/挂钩修改在 bash 提示符下输入的每个命令?
在我的理想世界中,脚本将在用户输入命令后但在按下 Enter 键之前触发。它将获取命令字符串作为参数,修改它并将其交给 bash 执行(这样一切都会透明地发生)。
我会使用这个钩子来进行一些公司特定的替换,这些替换无法使用别名来完成,但最重要的是,我对是否可以做到这一点感兴趣。
我知道有一些黑客可以在执行最后一个命令(trap 'function' DEBUG等等)后对其执行某些操作,因为有很多关于该场景的问题,但这在这里没有帮助。
谢谢并致以亲切的问候!