最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ruby - Rspec - How to replace receive by have_received when dealing with an expect within a block? - Stack Overflow

programmeradmin4浏览0评论

I have the following Ruby class I want to test:

class Logger
  # ...

  def process
    X.process
  rescue StandardError => e
    ::Rails.logger.error('Progname') { 'Could not produce the audit log' }
    ::Rails.logger.error('Progname') { e.message }
    ::Rails.logger.error('Progname') { e.backtrace.join("\n") }
  end
end

And my RSpec test that currently works:

require 'spec_helper'

describe Logger do
  before do
    stub_const('Rails', double('Rails', logger: rails_logger))
  end

  let(:rails_logger) { instance_double(Logger, error: nil) }

  describe '#process' do
    subject(:process) { log.process }

    context 'when an exception occurs' do
      let(:error) do
        StandardError.new('Something went wrong')
      end

      before do
        allow(X).to receive(:process).and_raise(error)
        allow(error).to receive(:backtrace)
          .and_return(['backtrace:1', 'backtrace:2'])
      end

      it 'logs an error message' do
        expect(rails_logger).to(receive(:error).with('Progname')) do |&block|
          expect(block.call).to eq('Could not produce the audit log')
        end

        expect(rails_logger).to(receive(:error).with('Progname')) do |&block|
          expect(block.call).to eq('Something went wrong')
        end

        expect(rails_logger).to(receive(:error).with('Progname')) do |&block|
          expect(block.call).to eq("backtrace:1\nbacktrace:2")
        end

        process
      end
    end
  end
end

Now I want to use the have_received form instead so I changed my code to:

it 'logs an error message' do
  process

  expect(rails_logger).to(have_received(:error).with('Progname')) do |&block|
    expect(block.call).to eq('Could not produce the audit log')
  end

  expect(rails_logger).to(have_received(:error).with('Progname')) do |&block|
    expect(block.call).to eq('Something went wrong')
  end

  expect(rails_logger).to(have_received(:error).with('Progname')) do |&block|
    expect(block.call).to eq("backtrace:1\nbacktrace:2")
  end        
end

but the block evaluation fails:

Failure/Error: expect(block.call).to eq('Could not produce the audit log')
     
       expected: "Could not produce the audit log"
            got: "Something went wrong"

It seems the strategy of the block evaluation is different there and if the expect within the block fails, instead of trying another expectation it fails immediately. I don't know how to rewrite my existing code.

Thanks.

发布评论

评论列表(0)

  1. 暂无评论