I am trying to get coverage on the following sections of code in my attached spec. This project prefers to use stubs over VCR and external API requests are blocked. Does anyone have any ideas on how to approach this issue to get the coverage needed?
I have the sleep test commented out because it is failing.
Code
def first_page
client.list_orders(created_before: created_before,
created_after: created_after,
max_results_per_page: max_results_per_page)
rescue Excon::Error::ServiceUnavailable => error
log_error(error, 'amazon_mws.errors.orders.first_page') unless (self.retries -= 1).positive?
add_api_delay
retry
end
def next_page(next_token)
client.list_orders_by_next_token(next_token)
rescue Excon::Error::ServiceUnavailable => error
log_error(error, 'amazon_mws.errors.orders.next_page') unless (self.retries -= 1).positive?
add_api_delay
retry
end
def add_api_delay
sleep(Configurations.amazon_mws['orders']['response_timer_in_seconds'])
end
Spec
describe '.poll_for_order_items' do
context 'multiple pages' do
before do
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItems&).*$/)
.to_return(body: next_page, status: 200, headers: { 'Content-Type': 'text/xml' })
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItemsByNextToken&).*$/)
.to_return(body: first_page, status: 200, headers: { 'Content-Type': 'text/xml' })
end
context 'with sleep stubbed' do
before do
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'returns array collection' do
expect(subject.poll_for_order_items).to be_kind_of(Array)
end
it 'returns array data' do
expect(subject.poll_for_order_items.length).to be > 0
end
end
# context 'with sleep set' do
# it 'should call sleep' do
# allow(Kernel).to receive(:sleep).and_return(1)
# expect(subject).to receive(:sleep).and_return(1)
# subject.poll_for_order_items
# end
# end
end
context 'single page' do
before(:each) do
stub_request(:any, /.*amazonservices.com.*/).to_return(body: first_page, status: 200, headers: { 'Content-Type': 'text/xml' })
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'returns array' do
expect(subject.poll_for_order_items).to be_kind_of(Array)
end
it 'returns array data' do
expect(subject.poll_for_order_items.length).to be > 0
end
end
context 'collector' do
before(:each) do
stub_request(:any, /.*amazonservices.com.*/).to_return(body: first_page_single, status: 200, headers: { 'Content-Type': 'text/xml' })
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'returns array when non array returned' do
expect(subject.poll_for_order_items).to be_kind_of(Array)
end
end
end
describe 'raises errors' do
context '.parse' do
let(:error_raised) { I18n.t('amazon_mws.errors.parse_payload') }
before do
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItems&).*$/)
.to_return(body: {}.to_json, status: 200, headers: { 'Content-Type': 'text/xml' })
end
it 'raises error' do
expect { subject.new } .to raise_error(StandardError)
end
end
context '.first_page' do
let(:error_raised) { I18n.t('amazon_mws.errors.order_items.first_page') }
before do
allow(MWS).to receive_message_chain(:orders, :list_order_items).and_raise(error_raised)
end
it 'raises error on first listing page' do
expect { subject.new } .to raise_error(StandardError)
end
end
context '.next_page' do
let(:error_raised) { I18n.t('amazon_mws.errors.order_items.next_page') }
before do
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItems&).*$/)
.to_return(body: next_page, status: 200, headers: { 'Content-Type': 'text/xml' })
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItemsByNextToken&).*$/)
.and_raise(error_raised)
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'raises error on nexst listing page' do
expect { subject.poll_for_order_items } .to raise_error(StandardError)
end
end
end
After research and inspiration from @wobh above I came up with the following...
describe '.poll_for_order_items' do
context 'multiple pages' do
before do
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItems&).*$/)
.to_return(body: next_page, status: 200, headers: { 'Content-Type': 'text/xml' })
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItemsByNextToken&).*$/)
.to_return(body: first_page, status: 200, headers: { 'Content-Type': 'text/xml' })
end
context 'with sleep stubbed' do
before do
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'returns array collection' do
expect(subject.poll_for_order_items).to be_kind_of(Array)
end
it 'returns array data' do
expect(subject.poll_for_order_items.length).to be > 0
end
end
end
context 'single page' do
before(:each) do
stub_request(:any, /.*amazonservices.com.*/).to_return(body: first_page, status: 200, headers: { 'Content-Type': 'text/xml' })
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'returns array' do
expect(subject.poll_for_order_items).to be_kind_of(Array)
end
it 'returns array data' do
expect(subject.poll_for_order_items.length).to be > 0
end
end
context 'collector' do
before(:each) do
stub_request(:any, /.*amazonservices.com.*/).to_return(body: first_page_single, status: 200, headers: { 'Content-Type': 'text/xml' })
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'returns array when non array returned' do
expect(subject.poll_for_order_items).to be_kind_of(Array)
end
end
end
describe 'raises errors' do
context '.parse' do
let(:error_raised) { I18n.t('amazon_mws.errors.parse_payload', error: 'TEST') }
before do
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItems&).*$/)
.to_return(body: {}.to_json, status: 200, headers: { 'Content-Type': 'text/xml' })
end
it 'raises error' do
expect { subject.poll_for_order_items } .to raise_error(StandardError)
end
it 'raises correct error message' do
expect { subject.poll_for_order_items } .to raise_error(/payload/)
end
end
context '.first_page' do
let(:error_raised) { I18n.t('amazon_mws.errors.order_items.first_page', error: 'TEST') }
before do
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItems&).*$/)
.to_raise(Excon::Error::ServiceUnavailable)
subject.instance_variable_set(:@retry_limit, 1)
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'raises error on first listing page' do
expect { subject.poll_for_order_items } .to raise_error(StandardError)
end
it 'raises correct error message' do
expect { subject.poll_for_order_items } .to raise_error(/order item first/)
end
end
context '.next_page' do
let(:error_raised) { I18n.t('amazon_mws.errors.order_items.next_page', error: 'TEST') }
before do
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItems&).*$/)
.to_return(body: next_page, status: 200, headers: { 'Content-Type': 'text/xml' })
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItemsByNextToken&).*$/)
.to_raise(Excon::Error::ServiceUnavailable)
subject.instance_variable_set(:@retry_limit, 1)
allow(subject).to receive(:add_api_delay).and_return(true)
end
it 'raises error on next listing page' do
expect { subject.poll_for_order_items } .to raise_error(StandardError)
end
it 'raises correct error message' do
expect { subject.poll_for_order_items } .to raise_error(/order item next/)
end
end
context '.add_api_delay' do
before do
stub_request(:any, /.*amazonservices.com.*/)
.with(body: /^.*(&Action=ListOrderItems&).*$/)
.to_raise(Excon::Error::ServiceUnavailable)
subject.instance_variable_set(:@retries, 2)
subject.instance_variable_set(:@retry_limit, 1)
subject.instance_variable_set(:@retry_delay, 1)
end
it 'sleeps retry api calls' do
allow(Kernel).to receive(:sleep).and_return(1)
expect(subject).to receive(:sleep).and_return(1)
expect { subject.poll_for_order_items } .to raise_error(StandardError)
end
end
end
THIS RESULTED IN 100% COVERAGE!