ruby 2.1 rails 4个太阳黑子solr测试在套件中失败但是单独通过

我的团队已经在这个问题上被困了一段时间,并且不知道接下来要去哪里尝试。 下面的规范在单独运行时可以正常工作,但是,当我们通过bundle exec ./bin/rspec spec在我们的套件中运行它时,这两个测试每次都会失败:

  • GET / external-products /:id / deals
  • GET /外部产品/搜索/交易

我们已经尝试了许多不同的方法来解决这个问题,我开始怀疑上述规范之外的其他内容。 所以我必须转向堆神,并请求那里有人有更好的方法,甚至更好的问题来问这个问题。

Rspec错误:

  8) Retailigence Products and Locations GET /external-products/search/deals Search a given region for related deals by query string Failure/Error: expect(response_body).to have_json_type(Integer).at_path('deals/0/id') JsonSpec::MissingPath: Missing JSON path "deals/0/id" # ./spec/features/external_products_spec.rb:151:in `block (3 levels) in ' # -e:1:in `' 9) Retailigence Products and Locations GET /external-products/:id/deals Search a given region for deals related to a particular product Failure/Error: expect(response_body).to have_json_type(Integer).at_path('deals/0/id') JsonSpec::MissingPath: Missing JSON path "deals/0/id" # ./spec/features/external_products_spec.rb:105:in `block (3 levels) in ' # -e:1:in `' 

这是我们的spec_helper.rb:

 require 'rubygems' ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) require 'rspec/rails' require 'email_spec' require 'pry' require 'rspec_api_documentation/dsl' require 'sunspot/rails/spec_helper' require 'sunspot_test/rspec' # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. Dir[Rails.root.join('spec/concerns/**/*.rb')].each { |f| require f } Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } # Checks for pending migrations before tests are run. # If you are not using ActiveRecord, you can remove this line. ActiveRecord::Migration.maintain_test_schema! # Model specs: type: :model # Controller specs: type: :controller # Request specs: type: :request # Feature specs: type: :feature # View specs: type: :view # Helper specs: type: :helper # Mailer specs: type: :mailer # Routing specs: type: :routing RSpec.configure do |config| config.order = 'random' config.seed = srand % 0xFFFF config.infer_spec_type_from_file_location! config.use_transactional_fixtures = false config.infer_base_class_for_anonymous_controllers = false config.before(:each) { GC.disable } config.after(:each) { GC.enable } config.include FactoryGirl::Syntax::Methods config.include JsonSpec::Helpers config.include Stubs config.include LoginHelper config.include SolrSpecHelper config.include SunspotMatchers config.include Devise::TestHelpers, type: :controller config.before do Sunspot.session = SunspotMatchers::SunspotSessionSpy.new(Sunspot.session) end config.before(:suite) do DatabaseCleaner.strategy = :truncation DatabaseCleaner.clean_with(:truncation) end config.before(:each) do DatabaseCleaner.strategy = :transaction end config.before(:each) do DatabaseCleaner.start end config.after(:each) do DatabaseCleaner.clean end end RspecApiDocumentation.configure do |config| config.format = :json end 

features / external_product_service_spec.rb

 resource 'Retailigence Products and Locations', type: :feature, api: true, slow: true, sunspot: true do before(:all) do log_in_as_client! end let(:id) { '7c381d47-d251-457a-a2d2-930c8993a5fa' } let(:lat) { 39.74585 } let(:long) { -104.998929 } let(:q) { 'whiteboard cleaner' } get '/external-products/:id' do parameter :id, 'The external id to search', required: true parameter :lat, 'The latitude to search', required: true parameter :long, 'The longitude to search', required: true parameter :radius, 'The radius, in miles, to search' example 'Search a given region for products matching a given external product id' do do_request user_email: @user.email, user_token: @token, timestamp: @timestamp expect(response_body).to have_json_type(Array).at_path('external_products') expect(response_body).to have_json_type(String).at_path('external_products/0/id') expect(response_body).to have_json_type(String).at_path('external_products/0/name') expect(response_body).to have_json_type(String).at_path('external_products/0/seo_slug') expect(response_body).to have_json_type(String).at_path('external_products/0/description') expect(response_body).to have_json_type(Array).at_path('external_products/0/images') expect(response_body).to have_json_type(String).at_path('external_products/0/price') end end get '/external-products/:id/external-stores' do parameter :id, 'The external id to search', required: true parameter :lat, 'The latitude to search', required: true parameter :long, 'The longitude to search', required: true parameter :radius, 'The radius, in miles, to search' example 'Search a given region for stores which have the product matching a given external product id' do do_request user_email: @user.email, user_token: @token, timestamp: @timestamp expect(response_body).to have_json_type(Array).at_path('external_stores') expect(response_body).to have_json_type(String).at_path('external_stores/0/id') expect(response_body).to have_json_type(String).at_path('external_stores/0/name') expect(response_body).to have_json_type(String).at_path('external_stores/0/store_logo') expect(response_body).to have_json_type(Float).at_path('external_stores/0/longitude') expect(response_body).to have_json_type(Float).at_path('external_stores/0/latitude') expect(response_body).to have_json_type(Float).at_path('external_stores/0/distance') expect(response_body).to have_json_type(String).at_path('external_stores/0/city') expect(response_body).to have_json_type(String).at_path('external_stores/0/address') expect(response_body).to have_json_type(String).at_path('external_stores/0/zip') expect(response_body).to have_json_type(String).at_path('external_stores/0/state') expect(response_body).to have_json_type(String).at_path('external_stores/0/phone_number') end end get '/external-products/search' do parameter :q, 'The query string to search', required: true parameter :lat, 'The latitude to search', required: true parameter :long, 'The longitude to search', required: true parameter :radius, 'The radius, in miles, to search' example 'Search a given region for products by query string' do do_request q: q, user_email: @user.email, user_token: @token, timestamp: @timestamp expect(response_body).to have_json_type(Array).at_path('external_products') expect(response_body).to have_json_type(String).at_path('external_products/0/id') expect(response_body).to have_json_type(String).at_path('external_products/0/name') expect(response_body).to have_json_type(String).at_path('external_products/0/seo_slug') expect(response_body).to have_json_type(String).at_path('external_products/0/description') expect(response_body).to have_json_type(Array).at_path('external_products/0/images') expect(response_body).to have_json_type(String).at_path('external_products/0/price') end end get '/external-products/:id/deals' do before(:each) do solr_setup store.location.save store.location.reload store.location.index! end let(:retailer) { create :retailer } let!(:deal) { create :deal, retailer_id: retailer.id } let!(:store) do create :store, retailer_id: retailer.id, location: (create :location, latitude: lat, longitude: long) end let!(:retailigence_retailer) do create :retailigence_retailers_retailer, retailer_id: retailer.id, retailigence_retailer_id: '39bfd9a5-f979-4ef1-816b-f9a38093494a' end let!(:content_location) do create :content_location, store_id: store.id, locatable_id: deal.id, locatable_type: 'Deal' end parameter :id, 'The external id to search', required: true parameter :lat, 'The latitude to search', required: true parameter :long, 'The longitude to search', required: true parameter :radius, 'The radius, in miles, to search' example 'Search a given region for deals related to a particular product' do do_request id: id, user_email: @user.email, user_token: @token, timestamp: @timestamp expect(response_body).to have_json_type(Array).at_path('deals') expect(response_body).to have_json_type(Integer).at_path('deals/0/id') expect(response_body).to have_json_type(Integer).at_path('deals/0/retailer_id') expect(response_body).to have_json_type(String).at_path('deals/0/title') expect(response_body).to have_json_type(String).at_path('deals/0/seo_slug') expect(response_body).to have_json_type(String).at_path('deals/0/name') expect(response_body).to have_json_type(String).at_path('deals/0/sort_name') expect(response_body).to have_json_type(String).at_path('deals/0/description') expect(response_body).to have_json_type(:boolean).at_path('deals/0/is_local') expect(response_body).to have_json_type(:boolean).at_path('deals/0/is_featured') expect(response_body).to have_json_type(Array).at_path('images') end end get '/external-products/search/deals' do before(:each) do solr_setup store.location.save store.location.reload store.location.index! end let(:retailer) { create :retailer } let!(:deal) { create :deal, retailer_id: retailer.id } let!(:store) do create :store, retailer_id: retailer.id, location: (create :location, latitude: lat, longitude: long) end let!(:retailigence_retailer) do create :retailigence_retailers_retailer, retailer_id: retailer.id, retailigence_retailer_id: 'eea1722b-ac89-4cce-95ec-26c2414646d7' end let!(:content_location) do create :content_location, store_id: store.id, locatable_id: deal.id, locatable_type: 'Deal' end parameter :q, 'The query string to search', required: true parameter :lat, 'The latitude to search', required: true parameter :long, 'The longitude to search', required: true parameter :radius, 'The radius, in miles, to search' example 'Search a given region for related deals by query string' do do_request q: q, lat: lat, long: long, user_email: @user.email, user_token: @token, timestamp: @timestamp expect(response_body).to have_json_type(Array).at_path('deals') expect(response_body).to have_json_type(Integer).at_path('deals/0/id') expect(response_body).to have_json_type(Integer).at_path('deals/0/retailer_id') expect(response_body).to have_json_type(String).at_path('deals/0/title') expect(response_body).to have_json_type(String).at_path('deals/0/seo_slug') expect(response_body).to have_json_type(String).at_path('deals/0/name') expect(response_body).to have_json_type(String).at_path('deals/0/sort_name') expect(response_body).to have_json_type(String).at_path('deals/0/description') expect(response_body).to have_json_type(:boolean).at_path('deals/0/is_local') expect(response_body).to have_json_type(:boolean).at_path('deals/0/is_featured') expect(response_body).to have_json_type(Array).at_path('images') end end end 

retailigence_service.rb:

 class RetailigenceService NEGATIVE_KEYWORDS = 'AND !DVD AND !CD AND !"compact disc"' MAX_QUERY_TIME = 5000 attr_accessor :products, :locations, :params def self.products(params = {}) fetch(params).products end def self.locations(params = {}) fetch_locations(params).locations end def self.fetch(params = {}) service = new service.fetch(params) service end def self.fetch_locations(params = {}) service = new service.fetch_locations(params) service end def fetch(params = {}) @params = { offset: 0, limit: 25 }.merge(params) @params.symbolize_keys! search_result = Retailigence::Product.search(search_params) @products = search_result.results build_products rescue Retailigence::NoResults @products = [] rescue Retailigence::APIException @products = [] end def fetch_locations(params = {}) @params = { offset: 0, limit: 25 }.merge(params) @params.symbolize_keys! Rails.logger.debug "[SENDING] #{location_params}" search_result = Retailigence::Location.search(location_params) @locations = search_result.results.map { |retailer| retailer.locations }.flatten build_locations rescue Retailigence::NoResults @locations = [] rescue Retailigence::APIException @locations = [] end private def keywords keywords = @params[:keywords] || '' keywords << ' ' << NEGATIVE_KEYWORDS keywords.gsub(/^\ AND\ /, '') end def page_size @params[:limit] end def page (@params[:offset] / @params[:limit]) + 1 end def location_params { userlocation: @params[:userlocation], requestorid: RETAILIGENCE_REQUESTOR_ID, productid: @params[:productid], pagesize: page_size, page: page, maxquerytime: MAX_QUERY_TIME, excludeadultcontent: true } end def search_params search_params = { userlocation: @params[:userlocation], requestorid: RETAILIGENCE_REQUESTOR_ID, pagesize: page_size, page: page, maxquerytime: MAX_QUERY_TIME, excludeadultcontent: true } search_params[:keywords] = keywords unless @params[:product_id] search_params[:productid] = @params[:product_id] if @params[:product_id] search_params end def format_price_prefix(prefix) prefix = '$' if prefix == 'USD' prefix end def build_products @products.map! do |p| p.images ||= [] p.description_long ||= '' RetailigenceProduct.new( id: p.id, name: p.name, seo_slug: p.name.slugify, description: p.description_long, images: p.images.map { |img| img.link }, price: "#{format_price_prefix p.msrp_currency}#{p.price}", retailigence_retailer_id: p.location.retailer.id) end end def build_locations @locations.map! do |l| RetailigenceLocation.new( id: l.id, name: l.retailer.name, latitude: l.latitude, longitude: l.longitude, phone_number: l.phone, address: l.address.address1, city: l.address.city, state: l.address.state, zip: l.address.postal, store_logo: l.retailer.logo, distance: l.distance.distance) end end end 

这是我们在支持/ sunspot.rb中的太阳黑子设置:

 $original_sunspot_session = Sunspot.session Sunspot.session = Sunspot::Rails::StubSessionProxy.new($original_sunspot_session) module SolrSpecHelper def solr_setup unless $sunspot $sunspot = Sunspot::Rails::Server.new pid = fork do STDERR.reopen('/dev/null') STDOUT.reopen('/dev/null') $sunspot.run end # shut down the Solr server at_exit { Process.kill('TERM', pid) } # wait for solr to start sleep 5 end Sunspot.session = $original_sunspot_session end end 

我之前没有遇到过这个确切的问题,但是我有两条建议/建议可能会对将来遇到它的人有所帮助。 如果您发现成功或不成功,请发表评论。

  1. 虽然不太理想,你可以从你的Gemfile测试组中删除’spring’gem,如果它已被包含在那里。

  2. 尝试运行bundle exec spring binstub --all以“弹出” bin/目录中的可执行文件。