簡體   English   中英

使用 RSpec 測試救援中的重試塊

[英]Using RSpec to test a retry block in a rescue

我在類中有一個實例方法,如下所示:

def get(path)
  try_request do
    RestClient.get(path, headers)
  end
end

並且try_request方法包含在代碼被搶救時的retry ,以便在執行某些操作以糾正 Unauthorized 異常后可以重新請求塊:

def try_request
  tries ||= 2
  EMS::Response.new(yield)
rescue RestClient::Unauthorized => e
  tries -= 1
  if tries.positive?
    ems_credentials.update_and_return_token
    retry
  end
  Rails.logger.error "Exception on #{e.class}: #{e.message}"
  EMS::Response.new(unauthorized_response)
end

所以我試圖通過以下測試來測試這個重試是否發生:

it 'retries and returns a successful response' do
  # allow the RestClient to raise an Unauthorized response
  allow(RestClient).to receive(:get).and_raise(RestClient::Unauthorized)
  # call the endpoint which would cause the above error
  described_class.new.get('/endpoint')
  # mock out a successful response:
  rest_response = double('rest_response', code: 200, body: { test: 'Test' }.to_json)
  # update the RestClient to return the successful response this time
  allow(RestClient).to receive(:get).and_return(rest_response)
  # retry the request and check the response is as expected:
  client_response = described_class.new.get('/endpoint')
  expect(client_response.code).to eq(200)
  expect(client_response.success?).to be_truthy
  expect(client_response.body[:test]).to eq('Test')
  expect(client_response).to be_an_instance_of(EMS::Response)
end

它通過並為我提供了該救援的完整代碼覆蓋率。

然而,實際發生的事情是,因為請求引發了錯誤,我們在這一點上立即結束: EMS::Response.new(unauthorized_response)並且因為我在測試中的這一點上沒有對expect做任何事情然后繼續測試(所以考慮所有調用的救援代碼)然后我們重新模擬響應並期望所以我們最終得到一個認為整個塊是完全測試代碼的測試......但我們不'實際上並沒有驗證是否發出請求......如果第一次引發異常,它會再次成功調用相同的方法,並且如果重試發生多次,則 THEN 成功響應或失敗。

如何正確測試這三種情況?

1.) 如果引發異常,測試請求是否再次重試。

2.) 測試如果第二次嘗試通過,我會得到成功的響應。

3.) 測試如果第二次嘗試失敗,那么我會得到最終的EMS::Response.new(unauthorized_response)響應。

希望這是有道理的? 我研究過使用should_receive(:retry)但我看不出我將如何使用它來驗證實際相同的代碼正在被重新調用,以及我如何驗證它只發生一次。

我會嘗試訂購

你應該能夠做到這一點

expect(RestClient).to receive(:get).ordered.and_raise(RestClient::Unauthorized)
expect(RestClient).to receive(:get).ordered.and_return(rest_response)
# ...
expect(client_response.code).to eq(200)

下一個例子

expect(RestClient).to receive(:get).ordered.and_raise(RestClient::Unauthorized)
expect(RestClient).to receive(:get).ordered.and_raise(RestClient::Unauthorized)
expect(RestClient).to receive(:get).ordered.and_return(rest_response)
# ...
expect(client_response.code).to eq(200)

最后

expect(RestClient).to receive(:get).ordered.and_raise(RestClient::Unauthorized)
# check that it was unsuccesfull

(如果你願意,你可以使用allow而不是expect ,我只是認為expect更合適)

如果這不起作用(我無法立即對其進行測試),您始終可以使用雙重期望的塊版本(但這會更難看)

errors_to_raise = 2
allow(RestClient).to receive(:get) do
  return rest_response if errors_to_raise <= 0
  errors_to_raise -= 1
  raise RestClient::Unauthorized
end
# ...
expect(client_response.code).to eq(200)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM