测试包含ActionController :: Live的控制器

Gau*_*nda 13 ruby rspec ruby-on-rails eventsource

我有一个包含Rails ActionController::Live模块的控制器.我显示一个日志文件,正在使用读取的内容FileTail宝石,并使用SSE来自ActionController::Live像这样:

class LogsController < ApplicationController
  include ActionController::Live

  def live
    response.headers['Content-Type'] = 'text/event-stream'
    sse = SSE.new(response.stream, event: 'queries')
    File.open(logfile_location) do |log|
      log.extend(File::Tail)
      log.interval = 1
      log.backward(10)
      log.tail {|line| sse.write line}
    end
  rescue => e
    Rails.logger.info "Error Message:: #{e.message}"
  ensure
    sse.close
  end
end
Run Code Online (Sandbox Code Playgroud)

我想用它来测试live动作Rspec.这就是我目前拥有的:

before { get :live }
it { expect(response.headers['Content-Type']).to eq("text/event-stream") }
after {response.stream.close unless response.stream.closed? }
Run Code Online (Sandbox Code Playgroud)

如果我没有after适当的线路,规范通过,但它只是继续监听,连接永远不会关闭,因此规格永远不会完成,你必须手动杀死它们.

如果我有这after条线,它有时会通过,但大多数时候它会抛出异常,并且规格失败.

fatal:
   No live threads left. Deadlock?
Run Code Online (Sandbox Code Playgroud)

有没有办法让这项工作成功?也许有一种特定的方式必须进行测试,这是无法找到的.

int*_*ale 1

您的应用程序中可能存在两个问题阻止您测试代码。

1)您使用的是旧版本的rails,不包含修复(rails 5+包含它)

File::Tail2)显然,当代码运行时没有退出点时,您正在使用这种方式。我的意思是:

File.open(logfile_location) do |log|
  log.extend(File::Tail)
  log.interval = 1
  log.backward(10)
  log.tail {|line| sse.write line}
end
Run Code Online (Sandbox Code Playgroud)

永远运行。

因此,您只需要存根File::Tail部分来负责永远运行代码或相应地修改您的代码(log.return_if_eof = Rails.env.test?会有帮助)。

在导轨 5.2.2 上进行测试。这段代码的工作原理:

describe "#live" do
  subject { process :live, method: :get }  

  its(:body) { is_expected.to include(file_content) } # file_content is content of your file
  its(:body) { is_expected.to include('event: queries') }
  its(:headers) { is_expected.to match(hash_including('Content-Type' => 'text/event-stream')) }
end
Run Code Online (Sandbox Code Playgroud)