如何测试是否使用了特定的Rack中间件?

4

更具体地说,我在谈论的是 sentry-ravensinatra。我看到了测试 sinatra 应用程序或中间件的示例。但是我没有看到测试特定中间件是否存在的示例。或者我应该测试行为而不是配置(或我应该如何称呼它)?

2个回答

1
重要的事情(我会说)是行为,但如果您希望检查中间件,我建议在深入研究Sinatra源代码后使用以下两种方法之一(可能有更简单/更好的方法):

环境变量(env)

在Sinatra源代码中,有一种使用env来检查中间件是否已经存在的方法:

# Behaves exactly like Rack::CommonLogger with the notable exception that it does nothing,
# if another CommonLogger is already in the middleware chain.
class CommonLogger < Rack::CommonLogger
  def call(env)
    env['sinatra.commonlogger'] ? @app.call(env) : super
  end

你可以在路由中做同样的事情,例如:

get "/env-keys" do
  env.keys.inspect
end

只有在中间件向env哈希表插入了某些内容时,它才会显示给你中间件,例如:

class MyBad
  def initialize app, options={}
    @app = app
    @options = options
  end

  def call env
    @app.call env.merge("mybad" => "I'm sorry!")
  end
end

输出:

["SERVER_SOFTWARE", "SERVER_NAME", "rack.input", "rack.version", "rack.errors", "rack.multithread", "rack.multiprocess", "rack.run_once", "REQUEST_METHOD", "REQUEST_PATH", "PATH_INFO", "REQUEST_URI", "HTTP_VERSION", "HTTP_HOST", "HTTP_CONNECTION", "HTTP_CACHE_CONTROL", "HTTP_ACCEPT", "HTTP_USER_AGENT", "HTTP_DNT", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "GATEWAY_INTERFACE", "SERVER_PORT", "QUERY_STRING", "SERVER_PROTOCOL", "rack.url_scheme", "SCRIPT_NAME", "REMOTE_ADDR", "async.callback", "async.close", "rack.logger", "mybad", "rack.request.query_string", "rack.request.query_hash", "sinatra.route"]

这是列表的末尾。
中间件方法 Sinatra::Base还有一种称为middleware的方法
  # Middleware used in this class and all superclasses.
  def middleware
    if superclass.respond_to?(:middleware)
      superclass.middleware + @middleware
    else
      @middleware
    end
  end

在模块化应用的类定义中调用它,你可以得到一个中间件数组:
require 'sinatra/base'

class AnExample < Sinatra::Base
  use MyBad
  warn "self.middleware = #{self.middleware}"

输出:

self.middleware = [[MyBad, [], nil]]

也许可以从Sinatra::Application中获取,但我还没有查看。

我并没有坚持测试非行为。如果中间件以某种方式表现出来,您可以考虑使用它。此外,我从“raven-ruby”团队那里得到了答案,但我还没有检查过。 - x-yuri
如果它以某种方式表现出来,那么它将影响行为,您可以检查。如果它不影响行为,那么问题在哪里?“我没有坚持测试而不是行为。”我不知道这是什么意思。 - ian
如果它以某种方式表现出来,那么它将影响行为,您可以检查它。所以我想知道如何检查。虽然我可能没有表达清楚。我不知道这是什么意思。我很乐意让任何人向我展示如何在此处测试行为,而不是状态(或配置,或其他任何东西)。 - x-yuri
@x-yuri,你链接的问题线程中的最后一条评论很好,可能需要使用should_receive进行模拟 - ian
如果您将此解决方案添加到您的答案中,我会接受它。 - x-yuri

0

ruby-raven的小伙伴们的帮助下,我们得到了这个:

ENV['RACK_ENV'] = 'test'

# the app: start

require 'sinatra'
require 'sentry-raven'

Raven.configure(true) do |config|
  config.dsn = '...'
end

use Raven::Rack

get '/' do
  'Hello, world!'
end

# the app: end

require 'rspec'
require 'rack/test'

Raven.configure do |config|
  logger = ::Logger.new(STDOUT)
  logger.level = ::Logger::WARN
  config.logger = logger
end

describe 'app' do
  include Rack::Test::Methods

  def app
    @app || Sinatra::Application
  end

  class TestRavenError < StandardError; end

  it 'sends errors to sentry' do
    @app = Class.new Sinatra::Application do
      get '/' do
        raise TestRavenError
      end
    end
    allow(Raven.client).to receive(:send).and_return(true)
    begin
      get '/'
    rescue TestRavenError
    end
    expect(Raven.client).to have_received(:send)
  end
end

或者如果发送请求的raven成为了问题(当测试失败不是因为底层错误,而是因为raven发送请求时),可以禁用它们:

Raven.configure(true) do |config|
  config.should_send = Proc.new { false }
end

并且模拟 Raven.send_or_skip

...
allow(Raven).to receive(:send_or_skip).and_return(true)
begin
  get '/'
rescue TestRavenError
end
expect(Raven).to have_received(:send_or_skip)
...

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