2013-10-15 2 views
0

Les documents VCR Cucumber montrent de nombreux exemples utilisant une minuscule application Sinatra pour simuler un serveur distant, en utilisant une fonction appelée start_sinatra_app chargée depuis vcr_cucumber_helpers.rb. Je voudrais utiliser quelque chose comme ça pour mes tests Rails/RSpec/VCR, mais je n'ai pas compris comment obtenir start_sinatra_app (ou équivalent) dans mon cadre de test. Mon approche naïve ne fonctionne pas car - il n'est pas surprenant - il ne peut pas trouver vcr_cucumber_helpers.rb.Comment utiliser Sinatra pour simuler un serveur distant dans RSpec/VCR?

Que dois-je ajouter à ce qui suit pour le faire fonctionner sous RSpec? Ou suis-je dans les mauvaises herbes et de faire tout faux?

# 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 

Répondre

1

Here's the code vous cherchez:

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 

À son tour, utilise VCR::LocalhostServer:

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

merci! - désolé je n'ai pas remarqué ta réponse plus tôt! –

0

Webmock fait cela très bien.

connexions à localhost Allow:

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

Et puis pointez votre URL à l'application:

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

Pour un exemple plus clair, voir:
http://robots.thoughtbot.com/how-to-stub-external-services-in-tests

Questions connexes