Как заглушить исключение с ошибкой в ​​RSpec? - PullRequest
1 голос
/ 25 июня 2019

Я не уверен, как подойти к тесту, когда он входит в часть исключения для следующего метода ".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 ]

1 голос
/ 25 июня 2019

Для проверки, если Rails logger вызывается 3 раза с разными сообщениями, вы можете комбинировать методы receive и ordered.

Также используйте 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

Надеюсь, это поможет

0 голосов
/ 25 июня 2019

Вы не можете заглушить 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
...