如何在RSpec中对异常进行存根处理?

时间:2019-06-25 17:42:00

标签: ruby-on-rails rspec stub

我不确定在进入“ .get”方法的异常部分时如何进行测试:

/api/reddit_client.rb

module Api
    class RedditClient

      def self.get(path, access_token)
        begin
          response = RestClient.get(
            path,
            { :Authorization => "Bearer #{access_token}" }
          )

          json_parse(response)
        rescue RestClient::ExceptionWithResponse => e
          logger.error "%%% Something went wrong in request post"
          logger.error "%%% It fails with error: #{e.http_code}"
          logger.error "%%% And with message: #{e.message}"

          { "message" => e.message, "error" => e.http_code }
        end
      end

      ...
      ...
      ...

        private

        def json_parse(response)
          JSON.parse(response.body)
        end
    end
end

我希望它测试是否引发“ RestClient :: ExceptionWithResponse”,为此,我执行了以下操作:

/api/reddit_client_spec.rb

require 'rails_helper'

RSpec.describe Api::RedditClient do
    let(:path) { 'https://www.somerandomapi.com' }
    let(:access_token) { 'f00TOk3N' }

    describe '.get' do
      subject { described_class.get(path, access_token)}

      context 'when not authorized' do
        before do
          allow(described_class)
            .to receive(:get)
            .and_raise(RestClient::ExceptionWithResponse)
        end

        it 'returns hash with error infos' do
          expect{ subject }.to raise_error(RestClient::ExceptionWithResponse)
        end
      end
    end
end

困扰我的是,我还想测试Rails.logger.error是否也被调用过3次,并检查我的哈希错误返回。如何测试这种情况?

2 个答案:

答案 0 :(得分:1)

要检查Rails logger是否因不同的消息而被调用3次,可以将receiveordered方法结合起来。

也可以使用RestClient代替Api::RedditClient来执行方法并捕获异常。

您的代码将如下所示:

 context 'when not authorized' do
   before do
     allow(RestClient) // <- Note that you should use RestClient instead of Api::RedditClient 
       .to receive(:get)
       .and_raise(RestClient::ExceptionWithResponse)
   end

   it 'should raise error' do
     expect(Rails.logger).to receive(:error).with("%%% Something went wrong in request post").ordered
     expect(Rails.logger).to receive(:error).with(""%%% It fails with error: 401"").ordered
     expect(Rails.logger).to receive(:error).with("%%% And with message: Exception Message").ordered

     expect{ subject }.to raise_error(RestClient::ExceptionWithResponse)
   end
 end

要检查返回响应,您可以在测试中抢救异常并检查返回类型

it 'returns hash with error infos' do
   expect{ subject rescue nil}.to include({ "message" => "Exception Message", "error" => 401 })
end

希望有帮助

答案 1 :(得分:0)

您不能对Api::RedditClient.get本身加桩,因为这样您要测试的代码将根本不会执行。

相反,例如,存根RestClient.get

allow(RestClient)
  .to receive(:get)
  .and_raise(RestClient::ExceptionWithResponse)

关于断言,rspec可以检查给定方法是否已被调用N次:

https://relishapp.com/rspec/rspec-mocks/v/3-5/docs/setting-constraints/receive-counts

expect(Rails.logger).to receive(:error).exactly(3).times