测试依赖于其他机架服务的机架服务

时间:2014-07-14 09:44:17

标签: ruby rspec sinatra rack

我正在重新考虑一个中型Web应用程序,它使用RSpec编写了许多单元测试和验收测试。我的主要目标是清理在生产中作为单独的机架应用程序运行的微服务的代码。当前的测试套件使用进程管理来启动和停止微服务,这会导致测试性能出现问题,并使测试环境管理测试夹具数据的方式变得复杂。

有数百个测试依赖于微服务的正确行为,这意味着在这个重新分解过程中,我将无法完全模拟或伪造微服务本身。但我真的想删除所有单独的流程处理和相关的成本。现在这是可行的,因为我正在为微服务本身添加单元测试,并且我们有一个独立的烟雾和集成测试基础设施,它已经与微服务一起运行,作为单独的基于机架的服务处理。

我创建了一个SSCE来证明这个问题。它有多个小文件,功能齐全,包括测试。对整体长度表示歉意,但我认为这是不可避免的,因为我的问题是关于如何组合这些多个组件。

微服务

微服务/ app.rb

require "grape"

class Microservice < Grape::API
  format      :json
  get '/main' do
    { :message => "Hello World!" }
  end
end

微服务/ config.ru

require File.join(File.dirname(__FILE__), "app")
run Microservice

微服务/规格/ spec_helper.rb

require_relative '../app.rb'

require 'rspec'
require 'rack/test'

def app
  Microservice
end

RSpec.configure do |config|
  config.include Rack::Test::Methods
end

微服务/规格/ microservice_spec.rb

require_relative 'spec_helper'

describe Microservice do
  describe "GET /main" do
    it "responds with correct JSON" do
      get "/main"
      expect( last_response ).to be_ok
      data = JSON.parse( last_response.body )
      expect( data ).to be == { "message" => "Hello World!" }
    end
  end
end

主Web应用程序

web应用程序/ app.rb

require 'sinatra'
require 'json'
require 'httparty'

# This stands in for more complex config we have in reality
$microservice_url = 'http://127.0.0.1:8090/'

get '/main' do
  # Calls a microservice . . . (annoyingly the service uses the same route name)
  response = HTTParty.get( $microservice_url + "main" )
  data = JSON.parse( response.body )
  "#{data['message']}\n"
end

web应用/规格/ spec_helper.rb

require_relative '../app.rb'

require 'rspec'
require 'rack/test'

def app
  Sinatra::Application
end

RSpec.configure do |config|
  config.include Rack::Test::Methods
end

# Is there something I can do here to load the
# microservice without launching it in a new process, and route
# the HTTParty.get in the main app to it?

$microservice_url = 'http://127.0.0.1:8888/'

web应用/规格/ webapp_spec.rb

require_relative 'spec_helper'

describe "Main web app" do
  describe "GET /main" do
    it "responds with correct text" do
      get "/main"
      expect( last_response ).to be_ok
      expect( last_response.body ).to include "Hello World!"
    end
  end
end

我可以轻松地运行微服务测试:

rspec -f d -c microservice/spec/microservice_spec.rb

但是要运行webapp测试,我首先需要启动测试期望找到它的微服务:

rackup -p 8888

(不同的过程)

rspec -f d -c webapp/spec/webapp_spec.rb

我认为我可以在应用程序中安装微服务,从查看How to mount a Sinatra application inside another Sinatra app?之类的问题,但这似乎适合在生产环境中加入应用程序,我需要将它们分开,只在单元测试中加入帮助程序启用它,到目前为止我完全失去了如何告诉HTTParty(或任何可以做我想要的替换)连接。


以下是我如何在示例中隐藏单个调用(在 webapp / spec / spec_helper.rb 结尾处) - 有没有办法将其路由到进程内反过来安装微服务?

require 'webmock/rspec'
include WebMock::API
stub_request( :any, /:8888\// ).to_return( :body => '{ "message":"Hello World!"}' )

1 个答案:

答案 0 :(得分:2)

WebMock提供routing to a Rack response,因此请microservice打包,以便webapp可以使用,然后您可以:

require 'microservice'
stub_request( :any, /:8888\// ).to_rack( Microservice )