RSpec - Jak testować serwis wykorzystujący httparty

Witam!
Mam pytanie w jaki sposób testujecie serwis który wykorzystuje api.
Mam serwis który wykorzystuje do wyszukiwania informacji o filmach. Wygląda on tak:

class OmdbService
  include HTTParty
  base_uri 'www.omdbapi.com'

  def initialize(title, year)
    @options = { query: { t: title, y: year, apikey: Rails.application.credentials.dig(:omdb, :apikey) } }
  end

  def search
    self.class.get('', @options)
  rescue HTTParty::Error => e
    inspect_errors(e)
  rescue StandardError => e
    inspect_errors(e)
    nil
  end

  def search_result
    search || NullOmdb.new
  end

  private

  def inspect_errors(error)
    logger.error error
  end

  def logger
    @logger ||= ::Logger.new("log/#{Rails.env}.log")
  end
end

Testuję tak:

require 'rails_helper'
RSpec.describe OmdbService do
  it 'fetches Title from api service' do
   expect(OmdbService.new('Terminator', '2019').search.parsed_response['Title']).to eq('Terminator: Dark Fate')
  end

  it 'fetches null object' do
    
  end
end

Pytanie - w jaki sposób można testować taki serwis? Jak np testować sytuację gdy nie mamy połączenia z internetem lub jeśli jest null?

obczaj vcr gem

1 Like

Dzięki sprawdzę. Czy wiesz może w jaki sposób testować np brak połączenia z internetem?

Jeśli dobrze zrozumiałem Twoje pytanie to nasuwa mi się pomysł aby odłączyć sobie internet i nagrać ten request używając VCR, ale nie jestem pewny co z tego wyjdzie :P.

Jeśli twój serwer nie ma połączenia z internetem to testowanie serwisu http jest wtedy najmniejszym zmartwieniem :joy:

Witaj :slight_smile: @fizzlebubble nie dokładnie o to mi chodziło. Sorry źle się wyraziłem. Jeśli odłączę internet przed nagraniem VCR to raczej nic z tego nie wyjdzie. Zresztą jak @soso zaznaczył jeśli nie ma internetu to nic nie będzie działać. Chodziło mi o to jak zachowa się serwis gdy np przestanie działać api lub nie będzie dostępny. W jaki sposób to można testować w rspec. Np jeśli zwróci pusty str ‘’

Dzięki

Gem VCR jest trudny do utrzymania w przypadku dużych projektów. Ogólnie polecam używać w szczególnej ostateczności. Testy powinny być wyizolowane. To co zaprezentowałeś mógłbyś zamockować w taki sposób:

    subject(:omdb_service) { described_class.new('Terminator', '2019') }

    let(:omdb_url) { "https://www.omdbapi.com" }
    let(:omdb_response) { instance_double(HTTParty::Response, body: omdb_response_body) }
    let(:omdb_response_body) { 'Terminator: Dark Fate' }

    before do
      allow(HTTParty).to receive(:get).and_return(omdb_response)
    end

    it 'fetches the titles from Omdb service' do
      expect(HTTParty).to have_received(:get).with(omdb_url)
    end

    it 'fetches Title from api service' do
      expect(omdb_service.search.parsed_response['Title']).to eq('Terminator: Dark Fate')
    end

Dla nullObject zrobiłbym oddzielny context i musi być let(:omdb_response_body) { nil }

Jeżeli wkradł się jakiś błąd to przepraszam, ale nie sprawdzałem tego kodu tylko tak na kolanie wykrzesałem. Myślę, że tędy Twoja droga jest :wink:

https://rspec.rubystyle.guide/#doubles

2 Likes

Dziękuje - o to mi chodziło.