2016-05-18 4 views
0

Ich versuche zu testen, dass 'ApiClient.do_request' die richtigen Argumente sendet und 'RestClient :: Request.execute' aufruft. ' Meine unten angegebenen Spezifikationen funktionieren jedoch nicht wie beabsichtigt. RSpec kann 'RestClient :: Request.execute' nicht ordnungsgemäß aufrufen, da die Variable 'response' der Methode immer als null zurückkommt, weshalb ich den folgenden TypeError erhalte, wenn JSON.parse (response) aufgerufen wird. Was mir seltsam ist, ist, dass ich keine Probleme habe, wenn ich den Prozess in der Rails-Konsole durchlaufe. Ich bin mir sicher, da ist etwas offensichtlich, das mir hier fehlt ... Irgendwelche Ideen, warum das passiert, oder vielleicht Vorschläge, wie ich das effektiver testen kann?RestClient :: Request.execute in RSpec testen

Modell:

class ApiClient < ActiveRecord::Base 

    BASE_PATH = "http://api.bandsintown.com/artists/" 
    APP_ID = ENV["APP_ID"] 

    def do_request(method:, base_url:BASE_PATH, app_id:APP_ID, url:, format:"json", options: nil) 
    response = RestClient::Request.execute(method: method.to_sym, 
              url: "#{base_url}#{url}.#{format}?api_version=2.0&app_id=#{app_id}#{options}", 
              timeout: 10) 

    JSON.parse(response) 
    end 

Spec:

describe ApiClient do 

    describe "do_request" do 

    context "when all required arguments are present" do 
     it "RestClient executes the request" do 
     @test_client = ApiClient.new 

     expect(RestClient::Request).to receive(:execute).with(:method=>:get, :url=> "http://api.bandsintown.com/artists/Damien%20Jurado/events/search.json?api_version=2.0&app_id=ShowBoatTest&location=San+Diego,CA&radius=15", :timeout=>10) 

     @test_client.do_request(method:"get", app_id:"ShowBoatTest",url:"Damien%20Jurado/events/search",options:"&location=San+Diego,CA&radius=15") 
     end 
    end 
    end 

RSpec Fehler:

1) ApiClient do_request when all required arguments are present RestClient executes the request 
Failure/Error: JSON.parse(response) 

TypeError: 
    no implicit conversion of nil into String 
# /Users/slamflipstrom/.rvm/gems/ruby-2.1.5/gems/json-1.8.3/lib/json/common.rb:155:in `initialize' 
# /Users/slamflipstrom/.rvm/gems/ruby-2.1.5/gems/json-1.8.3/lib/json/common.rb:155:in `new' 
# /Users/slamflipstrom/.rvm/gems/ruby-2.1.5/gems/json-1.8.3/lib/json/common.rb:155:in `parse' 
# ./app/models/api_client.rb:12:in `do_request' 
# ./spec/models/api_client_spec.rb:13:in `block (4 levels) in <top (required)>' 
+2

RSpec-Fehler scheint von einem anderen Test zu stammen. Nämlich "* wenn die Optionen für den Standort angefordert werden, erhält das Argument" Optionen "*". – Uzbekjon

+0

Sie sind in der Tat der gleiche Test, aber ich habe fälschlicherweise die Fehlermeldung von einer älteren Version enthalten. Ich habe den obigen RSpec-Fehler aktualisiert, um den aktualisierten Testnamen wiederzugeben. –

Antwort

1

Nicht kleinere Syntaxfehler wie api_version=2.0&app_id=ShowBoat in Ihrer ApiClient Klasse bedenkt, scheint das Problem verursacht werden durch Ihre RestClient::Request.execute Anfrage zurückgeben nil.

Debuggen oder inspizieren Sie den Wert response und stellen Sie sicher, dass es nicht ist.

class ApiClient < ActiveRecord::Base 

    BASE_PATH = "http://api.bandsintown.com/artists/" 
    APP_ID = ENV["APP_ID"] 

    def do_request(method:, base_url:BASE_PATH, app_id:APP_ID, url:, format:"json", options: nil) 
    response = RestClient::Request.execute(method: method.to_sym, 
              url: "#{base_url}#{url}.#{format}?api_version=2.0&app_id=#{app_id}#{options}", 
              timeout: 10) 
    puts response.inspect 
    response ? JSON.parse(response) : [] 
    end 

Auf der anderen Seite, testen Sie ApiClient Implementierung der Klasse. Mit anderen Worten, Sie testen, dass die Klasse intern eine andere Klasse auf spezifische Weise aufruft. Wenn Sie sich entscheiden, den RestClient zum Beispiel zu einem späteren Zeitpunkt durch HTTParty zu ersetzen, werden Ihre Tests fehlschlagen (obwohl dies nicht der Fall sein sollte, weil Ihre Klasse immer noch korrekt funktioniert).

Das Testen der Klassenimplementierung macht Ihre Tests also "fragil". Geben Sie stattdessen eine Eingabe und einen Test für die erwartete korrekte Ausgabe.

describe ApiClient do 
    context "with all required arguments" do 
    describe "#do_request" do 
     it "returns object in correct format" do 
     response = subject.do_request(method:"get", app_id:"ShowBoatTest",url:"Damien%20Jurado/events/search",options:"&location=San+Diego,CA&radius=15") 
     expect(response.body).to include(title: "Damien Jurado @ The Casbah in San Diego, CA") 
     # etc. 
     end 
    end 
    end 
end 
+0

Ich bin immer noch ratlos, warum die 'response'-Variable weiterhin als null zurückgegeben wird, aber das Feedback bezüglich der Testfragilität ist, was ich verdächtig war. So wie es aussieht, sollte ich den Test einfach ändern, um flexibler zu sein. Vielen Dank! –