测试Rails控制器使用throw:async的操作的正确方法是什么?

时间:2014-09-25 13:07:36

标签: ruby-on-rails rspec capybara thin

我有一个在Thin上运行的Rails服务器和一个异步控制器操作。我想用RSpec测试它,但是我收到一个错误:

 Failure/Error: get :access_token
     ArgumentError:
       uncaught throw :async

这是一个示例代码:

class SampleController < ApplicationController

  def sample
    EM.defer do
      render json: { response: 'Hello World' }

      request.env['async.callback'].call response
    end

    throw :async
  end

end

require 'spec_helper'

describe SampleController, :type => :controller do
  it "hello world" do
    get :sample
    expect(JSON.parse(response.body)[response]).to eq('Hello World')
  end
end

我收到此错误的原因是:async只能由Thin服务器处理。 vanilla Rails控制器中没有可用的瘦服务器。

所以试过Capybara:

  describe "GET /sample", type: feature do
    it "hello world" do
      visit sample_path

      expect(JSON.parse(page.body)['response']).to eq('Hello World')
    end
  end


  # In spec_helper.rb
  Capybara.server do |app, port|
    require 'rack/handler/thin'
    Rack::Handler::Thin.run(app, :Port => port)
  end

但我仍然得到同样的错误。我相信这是因为Thin需要以线程模式启动;而且水豚没有以这种方式启动它。

使用throw:async测试控制器操作的正确方法是什么?

当我使用常规浏览器访问它时,该操作会起作用。

2 个答案:

答案 0 :(得分:3)

为了测试使用Thin实现的异步Ruby on Rails操作,您需要使用Thin运行测试。否则它会失败,或者变脆 - 以防你尝试嘲笑。

所以让我们使用Capybara设置它:

在Gemfile中:

gem 'thin'
gem 'capybara'
gem 'selenium-webdriver'

在spec / rails_helper.rb中:

require 'capybara/rails' 

Capybara.default_driver = :selenium

Capybara.server do |app, port|
  require 'rack/handler/thin'
  Rack::Handler::Thin.run(app, :Port => port)
end

这将Capybara驱动程序设置为selenium,一个真正的浏览器。第二部分将Capybara服务器配置为Thin。

测试应该写成:

describe SampleController, :type => :feature do
  it "my test" do
    visit sample_path
    expect(page).to have_content('Hello World')
  end
end

这将使测试通过。

答案 1 :(得分:-1)

在RSpec控制器测试中,尝试替换

get :sample

expect { get :sample }.to throw_symbol(:async)

应该抓住它并防止规范失败。它还测试控制器是否异步!