From c9e567edb37bebc0ab0dc9f94e1e8c823a61d868 Mon Sep 17 00:00:00 2001 From: Akinori MUSHA Date: Fri, 4 Nov 2016 15:03:15 +0900 Subject: [PATCH] Fix the specs for HttpStatusAgent - Raplace hand-made mocking for web requests with Webmock - Stop overriding internal methods of Agent like `interpolated`, because that made the specs not reflect actual behavior --- spec/controllers/http_status_agent_spec.rb | 239 +++++++++++---------- 1 file changed, 129 insertions(+), 110 deletions(-) diff --git a/spec/controllers/http_status_agent_spec.rb b/spec/controllers/http_status_agent_spec.rb index 8c6c926e..722559ff 100644 --- a/spec/controllers/http_status_agent_spec.rb +++ b/spec/controllers/http_status_agent_spec.rb @@ -1,53 +1,29 @@ require 'rails_helper' -class MockResponse < Struct.new(:status, :headers, :url) - alias_method :to_hash, :to_h -end - describe 'HttpStatusAgent' do - - let(:agent) do - Agents::HttpStatusAgent.new(:name => SecureRandom.uuid, :options => valid_params).tap do |a| - a.service = services(:generic) - a.user = users(:jane) - a.options['url'] = 'http://google.com' - a.options['headers_to_save'] = 'Server' - a.save! - - def a.interpolate_with(e, &block) - @the_event = e - block.call - end - - def a.interpolated - @the_event.payload - end - - def a.create_event event - @the_created_events ||= [] - @the_created_events << event - end - - def a.the_created_events - @the_created_events || [] - end - - def a.faraday - @faraday ||= Struct.new(:programmed_responses).new({}).tap do |f| - def f.get url - programmed_responses[url] || raise('invalid url') - end - - def f.set url, response, time = nil - sleep(time/1000) if time - programmed_responses[url] = response - end - end - end - end + before do + stub_request(:get, 'http://google.com/') end - let(:valid_params) { {} } + let(:agent_options) do + { + url: 'http://google.com/', + headers_to_save: 'Server' + } + end + + let(:agent) do + Agents::HttpStatusAgent.create!( + name: SecureRandom.uuid, + service: services(:generic), + user: users(:jane), + options: agent_options + ) + end + + def created_events + agent.events.reorder(id: :asc) + end describe "working" do it "should be working when the last status is 200" do @@ -77,27 +53,21 @@ describe 'HttpStatusAgent' do end describe "check" do + let(:url) { "http://#{SecureRandom.uuid}/" } - before do - - def agent.interpolated - @interpolated ||= { :url => SecureRandom.uuid, :headers_to_save => '' } - end - - def agent.check_this_url url, local_headers - @url = url - @local_headers = local_headers - end - - def agent.checked_url - @url - end - + let(:agent_options) do + { + url: url, + headers_to_save: '' + } end it "should check the url" do + stub = stub_request(:get, url) + agent.check - expect(agent.checked_url).to eq(agent.interpolated[:url]) + + expect(stub).to have_been_requested end end @@ -106,15 +76,22 @@ describe 'HttpStatusAgent' do describe "with an event with a successful ping" do - let(:successful_url) { SecureRandom.uuid } + let(:successful_url) { "http://#{SecureRandom.uuid}/" } let(:status_code) { 200 } let(:header) { SecureRandom.uuid } let(:header_value) { SecureRandom.uuid } + before do + stub_request(:get, successful_url).to_return(status: status_code) + end + + let(:agent_options) do + super().merge(url: successful_url) + end + let(:event_with_a_successful_ping) do - agent.faraday.set(successful_url, MockResponse.new(status_code, {}, successful_url)) - Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: "" } } + Event.new(payload: { url: successful_url, headers_to_save: "" }) end let(:events) do @@ -123,17 +100,17 @@ describe 'HttpStatusAgent' do it "should create one event" do agent.receive events - expect(agent.the_created_events.count).to eq(1) + expect(created_events.count).to eq(1) end it "should note that the successful response succeeded" do agent.receive events - expect(agent.the_created_events[0][:payload]['response_received']).to eq(true) + expect(created_events.last[:payload]['response_received']).to eq(true) end it "should return the status code" do agent.receive events - expect(agent.the_created_events[0][:payload]['status']).to eq('200') + expect(created_events.last[:payload]['status']).to eq('200') end it "should remember the status" do @@ -143,51 +120,68 @@ describe 'HttpStatusAgent' do it "should record the time spent waiting for the reply" do agent.receive events - expect(agent.the_created_events[0][:payload]['elapsed_time']).not_to be_nil + expect(created_events.last[:payload]['elapsed_time']).not_to be_nil end it "should not return a header" do agent.receive events - expect(agent.the_created_events[0][:payload]['headers']).to be_nil + expect(created_events.last[:payload]['headers']).to be_nil end describe "but the last status code was 200" do - before { agent.memory['last_status'] = '200' } + before do + agent.memory['last_status'] = '200' + agent.save! + end describe "and no duplication settings have been set" do it "should create one event" do agent.receive events - expect(agent.the_created_events.count).to eq(1) + expect(created_events.count).to eq(1) end end describe "and change settings have been set to true" do - before { agent.options['changes_only'] = 'true' } + before do + agent.options[:changes_only] = 'true' + agent.save! + end + it "should NOT create any events" do agent.receive events - expect(agent.the_created_events.count).to eq(0) + expect(created_events.count).to eq(0) end describe "but actually, the ping failed" do - let(:failing_url) { SecureRandom.uuid } - let(:event_with_a_failing_ping) { Event.new.tap { |e| e.payload = { url: failing_url, headers_to_save: "" } } } + let(:failing_url) { "http://#{SecureRandom.uuid}/" } + let(:event_with_a_failing_ping) do + Event.new(payload: { url: failing_url, headers_to_save: "" }) + end let(:events) do [event_with_a_successful_ping, event_with_a_failing_ping] end + before do + stub_request(:get, failing_url).to_return(status: 500) + end + it "should create an event" do agent.receive events - expect(agent.the_created_events.count).to eq(1) + expect(created_events.count).to eq(1) end end end describe "and change settings have been set to false" do - before { agent.options['changes_only'] = 'false' } + before do + agent.options[:changes_only] = 'false' + agent.save! + end + it "should create one event" do agent.receive events - expect(agent.the_created_events.count).to eq(1) + expect(created_events.count).to eq(1) end end @@ -198,7 +192,7 @@ describe 'HttpStatusAgent' do it "should return the status code" do agent.receive events - expect(agent.the_created_events[0][:payload]['status']).to eq('500') + expect(created_events.last[:payload]['status']).to eq('500') end it "should remember the status" do @@ -209,39 +203,41 @@ describe 'HttpStatusAgent' do it "should return the original url" do agent.receive events - expect(agent.the_created_events[0][:payload]['url']).to eq(successful_url) + expect(created_events.last[:payload]['url']).to eq(successful_url) end it "should return the final url" do agent.receive events - expect(agent.the_created_events[0][:payload]['final_url']).to eq(successful_url) + expect(created_events.last[:payload]['final_url']).to eq(successful_url) end it "should return whether the url redirected" do agent.receive events - expect(agent.the_created_events[0][:payload]['redirected']).to eq(false) + expect(created_events.last[:payload]['redirected']).to eq(false) end describe "but the ping returns a status code of 0" do + before do + stub_request(:get, successful_url).to_return(status: 0) + end let(:event_with_a_successful_ping) do - agent.faraday.set(successful_url, MockResponse.new(0, {}, successful_url)) - Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: "" } } + Event.new(payload: { url: successful_url, headers_to_save: "" }) end it "should create one event" do agent.receive events - expect(agent.the_created_events.count).to eq(1) + expect(created_events.count).to eq(1) end it "should note that no response was received" do agent.receive events - expect(agent.the_created_events[0][:payload]['response_received']).to eq(false) + expect(created_events.last[:payload]['response_received']).to eq(false) end it "should return the original url" do agent.receive events - expect(agent.the_created_events[0][:payload]['url']).to eq(successful_url) + expect(created_events.last[:payload]['url']).to eq(successful_url) end it "should remember no status" do @@ -253,77 +249,91 @@ describe 'HttpStatusAgent' do end describe "but the ping returns a status code of -1" do + before do + stub_request(:get, successful_url).to_return(status: -1) + end let(:event_with_a_successful_ping) do - agent.faraday.set(successful_url, MockResponse.new(-1, {}, successful_url)) - Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: "" } } + Event.new(payload: { url: successful_url, headers_to_save: "" }) end it "should create one event" do agent.receive events - expect(agent.the_created_events.count).to eq(1) + expect(created_events.count).to eq(1) end it "should note that no response was received" do agent.receive events - expect(agent.the_created_events[0][:payload]['response_received']).to eq(false) + expect(created_events.last[:payload]['response_received']).to eq(false) end it "should return the original url" do agent.receive events - expect(agent.the_created_events[0][:payload]['url']).to eq(successful_url) + expect(created_events.last[:payload]['url']).to eq(successful_url) end end describe "and with one event with a failing ping" do - let(:failing_url) { SecureRandom.uuid } - let(:event_with_a_failing_ping) { Event.new.tap { |e| e.payload = { url: failing_url, headers_to_save: "" } } } - + let(:failing_url) { "http://#{SecureRandom.uuid}/" } + let(:event_with_a_failing_ping) do + Event.new(payload: { url: failing_url, headers_to_save: "" }) + end let(:events) do [event_with_a_successful_ping, event_with_a_failing_ping] end + before do + stub_request(:get, failing_url).to_raise(RuntimeError) #to_return(status: 500) + end + it "should create two events" do agent.receive events - expect(agent.the_created_events.count).to eq(2) + expect(created_events.count).to eq(2) end it "should note that the failed response failed" do agent.receive events - expect(agent.the_created_events[1][:payload]['response_received']).to eq(false) + expect(created_events[1][:payload]['response_received']).to eq(false) end it "should note that the successful response succeeded" do agent.receive events - expect(agent.the_created_events[0][:payload]['response_received']).to eq(true) + expect(created_events[0][:payload]['response_received']).to eq(true) end it "should return the original url on both events" do agent.receive events - expect(agent.the_created_events[0][:payload]['url']).to eq(successful_url) - expect(agent.the_created_events[1][:payload]['url']).to eq(failing_url) + expect(created_events[0][:payload]['url']).to eq(successful_url) + expect(created_events[1][:payload]['url']).to eq(failing_url) end it "should record the time spent waiting for the reply" do agent.receive events - expect(agent.the_created_events[0][:payload]['elapsed_time']).not_to be_nil - expect(agent.the_created_events[1][:payload]['elapsed_time']).not_to be_nil + expect(created_events[0][:payload]['elapsed_time']).not_to be_nil + expect(created_events[1][:payload]['elapsed_time']).not_to be_nil end end describe "with a header specified" do + before do + stub_request(:get, successful_url).to_return( + status: status_code, + headers: { header => header_value } + ) + end + let(:event_with_a_successful_ping) do - agent.faraday.set(successful_url, MockResponse.new(status_code, {header => header_value}, successful_url)) - Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: header } } + Event.new(payload: { url: successful_url, headers_to_save: header }) end it "should return the header value" do agent.receive events - expect(agent.the_created_events[0][:payload]['headers']).not_to be_nil - expect(agent.the_created_events[0][:payload]['headers'][header]).to eq(header_value) + event = created_events.last + expect(event[:payload]['headers']).not_to be_nil + expect(event[:payload]['headers'][header]).to eq(header_value) end end @@ -331,19 +341,28 @@ describe 'HttpStatusAgent' do describe "with existing and non-existing headers specified" do let(:nonexistant_header) { SecureRandom.uuid } + before do + stub_request(:get, successful_url).to_return( + status: status_code, + headers: { header => header_value } + ) + end + let(:event_with_a_successful_ping) do - agent.faraday.set(successful_url, MockResponse.new(status_code, {header => header_value}, successful_url)) - Event.new.tap { |e| e.payload = { url: successful_url, headers_to_save: header + "," + nonexistant_header } } + Event.new(payload: { + url: successful_url, + headers_to_save: header + "," + nonexistant_header + }) end it "should return the existing header's value" do agent.receive events - expect(agent.the_created_events[0][:payload]['headers'][header]).to eq(header_value) + expect(created_events.last[:payload]['headers'][header]).to eq(header_value) end it "should return nil for the nonexistant header" do agent.receive events - expect(agent.the_created_events[0][:payload]['headers'][nonexistant_header]).to be_nil + expect(created_events.last[:payload]['headers'][nonexistant_header]).to be_nil end end