2013-10-15 3 views
0

VCR Cucumber 문서는 vcr_cucumber_helpers.rb에서로드 된 start_sinatra_app이라는 함수를 사용하여 작은 Sinatra 앱을 사용하여 원격 서버를 시뮬레이션하는 많은 예를 보여줍니다.RSpec/VCR에서 Sinatra를 사용하여 원격 서버를 시뮬레이션하려면 어떻게해야합니까?

레일즈/RSpec/VCR 테스트에 사용하고 싶지만 start_sinatra_app (또는 동급)을 테스트 프레임 워크로 가져 오는 방법을 찾지 못했습니다. 내 순진한 접근 방식은 작동하지 않습니다 - 당연하지 - vcr_cucumber_helpers.rb을 찾을 수 없습니다.

RSpec에서 작동하게하려면 다음을 추가해야합니까? 아니면 잡초에서 벗어나이 모든 일을 잘못 했습니까? 다시 사용

def start_sinatra_app(options, &block) 
    raise ArgumentError.new("You must pass a port") unless options[:port] 

    require 'sinatra' 
    require 'support/vcr_localhost_server' 
    klass = Class.new(Sinatra::Base) 
    klass.disable :protection 
    klass.class_eval(&block) 

    VCR::LocalhostServer.new(klass.new, options[:port]) 
end 

그건 VCR::LocalhostServer :

# file: spec/app/models/sinatra_test_spec.rb 
require 'spec_helper' 

start_sinatra_app(:port => 7777) do 
    get("/") { "Hello" } 
end 

describe "sinatra rspec test" do 
    it 'calls the sinatra app' do 
    VCR.use_cassette("sinatra_rspec_test") do 
     res = Net::HTTP.get_response('localhost', "/", 7777) 
     res.body.should == 'Hello' 
    end 
    end 
end 

답변

1

Here's the code 당신이 찾고있는

require 'rack' 
require 'rack/handler/webrick' 
require 'net/http' 

# The code for this is inspired by Capybara's server: 
# http://github.com/jnicklas/capybara/blob/0.3.9/lib/capybara/server.rb 
module VCR 
    class LocalhostServer 
    READY_MESSAGE = "VCR server ready" 

    class Identify 
     def initialize(app) 
     @app = app 
     end 

     def call(env) 
     if env["PATH_INFO"] == "/__identify__" 
      [200, {}, [VCR::LocalhostServer::READY_MESSAGE]] 
     else 
      @app.call(env) 
     end 
     end 
    end 

    attr_reader :port 

    def initialize(rack_app, port = nil) 
     @port = port || find_available_port 
     @rack_app = rack_app 
     concurrently { boot } 
     wait_until(10, "Boot failed.") { booted? } 
    end 

    private 

    def find_available_port 
     server = TCPServer.new('127.0.0.1', 0) 
     server.addr[1] 
    ensure 
     server.close if server 
    end 

    def boot 
     # Use WEBrick since it's part of the ruby standard library and is available on all ruby interpreters. 
     options = { :Port => port } 
     options.merge!(:AccessLog => [], :Logger => WEBrick::BasicLog.new(StringIO.new)) unless ENV['VERBOSE_SERVER'] 
     Rack::Handler::WEBrick.run(Identify.new(@rack_app), options) 
    end 

    def booted? 
     res = ::Net::HTTP.get_response("localhost", '/__identify__', port) 
     if res.is_a?(::Net::HTTPSuccess) or res.is_a?(::Net::HTTPRedirection) 
     return res.body == READY_MESSAGE 
     end 
    rescue Errno::ECONNREFUSED, Errno::EBADF 
     return false 
    end 

    def concurrently 
     # JRuby doesn't support forking. 
     # Rubinius does, but there's a weird issue with the booted? check not working, 
     # so we're just using a thread for now. 
     Thread.new { yield } 
    end 

    def wait_until(timeout, error_message, &block) 
     start_time = Time.now 

     while true 
     return if yield 
     raise TimeoutError.new(error_message) if (Time.now - start_time) > timeout 
     sleep(0.05) 
     end 
    end 
    end 
end 
+0

감사합니다! - 죄송합니다. 귀하의 답변을 더 빨리 알 수 없었습니다! –

0

Webmock는 아주 능숙하게이 작업을 수행합니다.

는 로컬 호스트에 연결을 허용 : 다음

# spec/spec_helper.rb  
require 'webmock/rspec' 
WebMock.disable_net_connect!(allow_localhost: true) 

앱에 URL을 가리 킵니다 :

# spec/spec_helper.rb 
RSpec.configure do |config| 
    config.before(:each) do 
    stub_request(:any, /api.github.com/).to_rack(SinatraApp) 
    end 
end 

명확한 예를 들어, 참조 :
http://robots.thoughtbot.com/how-to-stub-external-services-in-tests