2017-01-11 6 views
0

添付の仕様書の次のコードセクションを対象としています。このプロジェクトはVCRよりもスタブを使用し、外部API要求はブロックされます。どの人がこの問題にアプローチしてカバレッジを得るためのアイデアを持っていますか?レスキューを使用するときにカバレッジを取得し、Rspec 3.5でVCRではなくスタブを使用して再試行する方法は?

私は睡眠テストが失敗したためコメントアウトしました。

コード

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 

スペック

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 

カバレッジレポート enter image description here

答えて

0

...

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 

これは、100%のカバレッジをもたらしました!

0

私はあなたがそれがエラーを発生させるために期待していることがわかります。タイムアウトした場合は、log_erroradd_api_delayを少なくとも1回呼び出す必要があります。これらは基本的な副作用であるため、あなたはその状況で呼び出されるとテストする必要があり、カバレッジレポートはそのことを知っている必要があります。

試しのような期待を追加:expect(subject).to have_received(:log_error).at_least(:once)

EDIT:アウト・オブ・バンド、それについて話すと、私たちはエラーが発生していることを確認することによって解決することができ、カバレッジの問題のほとんどを学びました。私は、次のを思い付いた上@wobhから研究とインスピレーションの後

before do stub_request(:any, /.*amazonservices.com.*/) .with(body: /^.*(&Action=ListOrders&).*$/) .to_raise(Excon::Error::ServiceUnavailable) end

関連する問題