23

再試行ブロックがあります

 def my_method
    app_instances = []
    attempts = 0
    begin 
      app_instances = fetch_and_rescan_app_instances(page_n, policy_id, policy_cpath)
    rescue Exception
      attempts += 1
      retry unless attempts > 2
      raise Exception 
    end
    page_n += 1
  end

ネットワークにfetch_and_rescan_app_instancesアクセスするため、例外をスローできます。

最初に例外をスローし、2回目に呼び出されたときに例外をスローしないという、rspecテストを作成したいので、2回目に例外をスローしない場合、my_methodが例外をスローしないかどうかをテストできます。例外。

私はできることを知ってstub(:fetch_and_rescan_app_instances).and_return(1,3)おり、最初は1を返し、2回目は3を返しますが、最初に例外をスローして2回目に何かを返す方法がわかりません。

4

3 に答える 3

24

ブロック内の戻り値を計算できます。

describe "my_method" do
  before do
    my_instance = ...
    @times_called = 0
    my_instance.stub(:fetch_and_rescan_app_instances).and_return do
      @times_called += 1
      raise Exception if @times_called == 1
    end
  end

  it "raises exception first time method is called" do
    my_instance.my_method().should raise_exception
  end

  it "does not raise an exception the second time method is called" do
    begin
      my_instance.my_method()
    rescue Exception
    end
    my_instance.my_method().should_not raise_exception
  end
end

から救助するべきではないことに注意してくださいException。より具体的なものを使用してください。参照:Rubyで `rescue Exception => e`を実行するのが悪いスタイルなのはなぜですか?

于 2013-01-08T02:25:07.693 に答える
21

あなたがすることは、メッセージが受信されるべき時間(受信カウント)を制限することです、すなわちあなたの場合、あなたはすることができます

instance.stub(:fetch_and_rescan_app_instances).once.and_raise(RuntimeError, 'fail')
instance.stub(:fetch_and_rescan_app_instances).once.and_return('some return value')

最初に呼び出すinstance.fetch_and_rescan_app_instancesとRuntimeErrorが発生し、2回目に呼び出すと「何らかの戻り値」が返されます。

PS。それ以上呼び出すとエラーが発生するため、別の受信カウント仕様を使用することを検討してくださいhttps://www.relishapp.com/rspec/rspec-mocks/docs/message-expectations/receive-counts

于 2013-09-10T10:16:08.220 に答える
11

これはRSpec3.xで少し変更されました。最善のアプローチは、receiveこのタイプの動作を定義するブロックをに渡すことです。

以下は、このタイプのトランジット障害を作成する方法を提案するドキュメントからのものです。

(このエラーは、呼び出されるたびに発生します。..しかし、簡単に適応できます。)

RSpec.describe "An HTTP API client" do
  it "can simulate transient network failures" do
    client = double("MyHTTPClient")

    call_count = 0
    allow(client).to receive(:fetch_data) do
      call_count += 1
      call_count.odd? ? raise("timeout") : { :count => 15 }
    end

    expect { client.fetch_data }.to raise_error("timeout")
    expect(client.fetch_data).to eq(:count => 15)
    expect { client.fetch_data }.to raise_error("timeout")
    expect(client.fetch_data).to eq(:count => 15)
  end
end
于 2016-10-24T12:52:20.613 に答える