上下文:应用程序使用一段必须在config.ru 中设置的Rack 中间件,而不是Rails 的内部中间件链。这是出于与此问题无关的原因。
问题:如何让我的测试(功能和集成)知道这个中间件?
我将举例说明。让我们使用 rack-rewrite 创建一个原始的 Rails 3 应用程序用于说明目的。
# /config/initializers/example.rb
Rails.application.middleware.insert 0, 'Rack::Rewrite' do
r301 '/so', 'http://stackoverflow.com'
end
# /test/integration/the_test.rb
require 'test_helper'
class TheTest < ActionDispatch::IntegrationTest
test "redirect from /so to http://stackoverflow.com" do
get '/so'
assert_redirected_to 'http://stackoverflow.com'
end
end
如果您运行上面的测试,一切都很好,并且您可以通过浏览器确认访问路径 /so
确实会将您重定向到 StackOverflow。
很酷,现在让我们在 Rails 之外设置它。删除上述文件 /config/initializers/example.rb
,并将 config.ru
更改为以下内容:
# /config.ru
require ::File.expand_path('../config/environment', __FILE__)
map '/so' do
run Rack::Rewrite do
r301 '', 'http://stackoverflow.com'
end
end
map '/' do
run Deleteme::Application
end
现在,测试将停止工作。该功能确实有效,如果您使用浏览器访问 /so
就证明了这一点。只是测试不知道该 Rack 设置。
最佳答案
(感谢 Dan Croak 让我走上正轨。这个答案完善了他所说的话)。
简答
无法进行功能测试。
对于集成测试,将以下内容添加到您的 test_helper.rb:
ActionDispatch::IntegrationTest.app = Rack::Builder.new do
eval File.read(Rails.root.join('config.ru'))
end
长答案
功能测试只是针对 Controller 运行的单元测试。例如,当您说 get :index
时,您并不是在解析路由。相反,这是调用 index
方法的简写,请求环境包括对 HTTP 方法的提及 GET。
因此,您的 Rack 堆栈不会影响功能测试是有道理的。
集成测试是另一回事。你在那里测试你的完整堆栈,所以你也想测试你的 Rack 中间件。唯一的问题是,默认情况下,这些测试只会看到您使用 Rails 自己的 API 添加的中间件。
但我说“默认”是因为 Rails 提供了一种方法来更改要测试的 Rack 堆栈。默认情况下,集成测试会为其请求调用 Rails.application
。您可以将其更改为适合您需要的任何内容。
通过使用上面的代码,我们使用 Rack::Builder
创建一个 ad-hoc Rack 应用程序。在 block 内,您可以将通常放在 config.ru
文件中的任何代码放入其中。为了避免代码重复,eval
加载我们的 config.ru
文件。现在我们的集成测试将加载与我们的应用服务器公开的完全相同的应用程序。
关于ruby-on-rails - 让 Rails 测试知道 Rails 内部链之外的 Rack 中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5016690/