【问题标题】:Getting Rspec unit test coverage with Rails and PostgreSQL使用 Rails 和 PostgreSQL 获得 Rspec 单元测试覆盖率
【发布时间】:2019-01-22 00:13:33
【问题描述】:

我正在尝试为以下模型问题编写单元测试...

require 'active_support/concern'

module Streamable
  extend ActiveSupport::Concern

  def stream_query_rows(sql_query, options = 'WITH CSV HEADER')
    conn = ActiveRecord::Base.connection.raw_connection
    conn.copy_data("COPY (#{sql_query}) TO STDOUT #{options};") do
      binding.pry
      while row = conn.get_copy_data
        binding.pry
        yield row
      end
    end
  end
end

到目前为止,我一直在与以下规范作斗争...

context 'streamable' do
  it 'is present' do
    expect(described_class.respond_to?(:stream_query_rows)).to eq(true)
  end

  context '#stream_query_rows', focus: true do
    let(:sql_query) { 'TESTQRY' }
    let(:sql_query_options) { 'WITH CSV HEADER' }
    let(:raw_connection) do
      Class.new do
        def self.copy_data(args)
          yield
        end

        def self.get_copy_data
          return Proc.new { puts 'TEST' }
        end
      end
    end

    before do
      allow(ActiveRecord::Base).to receive_message_chain(:connection, :raw_connection).and_return(raw_connection)

      described_class.stream_query_rows(sql_query)
    end


    it 'streams data from the db' do
      expect(raw_connection).to receive(:copy_data).with("COPY (#{sql_query}) TO STDOUT #{sql_query_options};")
    end
  end
end

虽然我可以让第一个期望通过,这意味着,我可以触发第一个 binding.pry,无论我尝试什么,我似乎都无法通过第二个。

这是错误...

LocalJumpError:
       no block given (yield)

我只是想对此进行单元测试,理想情况下不打数据库,只测试对象的通信。这也可以并且将在许多模型中用作流数据的选项。

参考文章:https://shift.infinite.red/fast-csv-report-generation-with-postgres-in-rails-d444d9b915ab

是否有人对如何完成此存根和/或调整规范有一个指示,以便我涵盖以下块?

   while row = conn.get_copy_data
        binding.pry
        yield row
      end

回答

在查看了下面的 cmets 和建议后,我能够重构规范,现在有 100% 的覆盖率。

  context '#stream_query_rows' do
    let(:sql_query) { 'TESTQRY' }
    let(:sql_query_options) { 'WITH CSV HEADER' }
    let(:raw_connection) { double('RawConnection') }
    let(:stream_query_rows) do
      described_class.stream_query_rows(sql_query) do
        puts sql_query
        break
      end
    end

    before do
      allow(raw_connection).to receive(:copy_data).with("COPY (#{sql_query}) TO STDOUT #{sql_query_options};"){ |&block| block.call }
      allow(raw_connection).to receive(:get_copy_data).and_return(sql_query)
      allow(ActiveRecord::Base).to receive_message_chain(:connection, :raw_connection).and_return(raw_connection)
    end

    it 'streams data from the db' do
      expect(raw_connection).to receive(:copy_data).with("COPY (#{sql_query}) TO STDOUT #{sql_query_options};")
      stream_query_rows
    end

    it 'yields correct data' do
      expect { stream_query_rows }.to output("#{sql_query}\n").to_stdout_from_any_process
    end
  end

【问题讨论】:

    标签: ruby-on-rails postgresql rspec tdd


    【解决方案1】:

    就像错误所说的那样,你是 yielding,但你没有提供一个块供它调用。

    如果您的方法需要一个块,那么您需要在调用它时提供一个。

    为此,您需要更改此行:

          described_class.stream_query_rows(sql_query)
    

    到这样的事情:

          described_class.stream_query_rows(sql_query) { puts "this is a block" }
    

    【讨论】:

    • 我了解@mattewd 的错误,但您将如何调整存根来完成此操作?
    • 问题与存根无关。你在一个地方打电话给stream_query_rows,但你没有通过一个街区。
    • 也许我没有关注你,你能把你打电话的方式贴出来吗,我认为这会更有帮助。我很感激。
    • 我已将确切的更改编辑为答案。这有帮助吗?
    • 是的,先生,在您的帮助下,我能够解决这个问题。再次感谢您。
    猜你喜欢
    • 2014-04-06
    • 2017-11-08
    • 2018-10-18
    • 2014-05-11
    • 2019-06-28
    • 2014-11-18
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    相关资源
    最近更新 更多