Rails 4:如何在集成测试期间从Rails应用程序外部发出请求?

Rails 4: how to make request from outside of Rails app during integration test?

我有一个应用程序需要与外部守护程序 (bitcoind) 进行双向通信。 bitcoind 中的功能允许在新块或感兴趣的交易发生时调用我的应用程序('--walletnotify' 和 '--blocknotify')。为此,我使用 CURL 来请求“http://myapp/walletnotify”等等:

walletnotify = /usr/bin/curl --max-time 60 http://myapp/walletnotify/%s

我正在尝试为此回调行为创建集成测试。不幸的是,当 运行ning 集成测试时,我在守护程序端收到错误,因为它无法执行对“http://myapp/walletnotify”的请求 - 显然 Rails 服务器无法访问(或连接中断?)。当然,测试失败是因为没有调用适当的操作。

我的问题是:如何正确测试这种情况?有什么方法可以在集成测试期间允许对应用程序的直接外部请求?有没有办法确保 Rails 服务器在集成测试期间处于 运行ning 状态?或者我应该在集成测试中听取此类请求,然后将它们代理到应用程序?

2018-06-03 更新:我正在使用 minitest。我正在尝试 运行 的测试在这里:

https://github.com/cryptogopher/token_voting/blob/master/test/integration/token_votes_notify_test.rb

调用后

@rpc.generate(101)

regtest 模式下的 bitcoind 守护程序应生成 101 个块并调用 'blocknotify' 回调。问题是它无法在测试期间向应用程序发送 HTTP 请求。

好的,我解决了这个问题。

看起来 'minitest' 不会启动应用程序服务器,无论您选择哪个 driver。您仍然可以启动自己的 HTTP 服务器来侦听来自外部源的通知并将它们转发给测试的应用程序。

为此,您需要:

require 'webrick'

设置 HTTP 服务器(禁用日志记录以避免混乱):

server = WEBrick::HTTPServer.new(
  Port: 3000,
  Logger: WEBrick::Log.new("/dev/null"),
  AccessLog: []
)

指定如何处理传入的 HTTP 请求。在我的例子中,只有 GET 请求,但重要的是用原始 headers:

转发它们
server.mount_proc '/' do |req, resp|
  headers = {}
  req.header.each { |k,v| v.each { |a| headers[k] = a } }
  resp = get req.path, {}, headers
end

在单独的线程中启动 HTTP 服务器(它阻塞了它所在的线程 运行):

@t = Thread.new {
  server.start
}
Minitest.after_run do
  @t.kill
  @t.join
end
Timeout.timeout(5) do
  sleep 0.1 until server.status == :Running
end