VCR Cucumber文档显示了许多使用小型Sinatra应用程序模拟远程服务器的示例,使用从start_sinatra_app
加载的名为vcr_cucumber_helpers.rb
的函数。
我想在我的Rails / RSpec / VCR测试中使用类似的东西,但还没有弄清楚如何将start_sinatra_app
(或等效的)放入我的测试框架中。我的天真方法不起作用 - 毫不奇怪 - 它找不到vcr_cucumber_helpers.rb
。
我需要添加以下内容才能使其在RSpec下运行?或者我是在杂草丛生中做错了吗?
# 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
答案 0 :(得分:1)
Here's the code您正在寻找:
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:
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
答案 1 :(得分:0)
Webmock做得非常好。
允许连接到localhost:
# spec/spec_helper.rb
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
然后将您的网址指向该应用:
# 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