使用 Rails 和 PostgreSQL 获得 Rspec 单元测试覆盖率
Getting Rspec unit test coverage with Rails and PostgreSQL
我正在尝试为以下模型问题编写单元测试...
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
回答
查看下面的评论和建议后,我能够重构规范,现在覆盖率达到 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
如错误所述,您正在 yield
ing,但您没有提供块供其调用。
如果您的方法需要一个块,那么您需要在调用它时提供一个块。
为此,您需要更改此行:
described_class.stream_query_rows(sql_query)
像这样:
described_class.stream_query_rows(sql_query) { puts "this is a block" }
我正在尝试为以下模型问题编写单元测试...
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
回答
查看下面的评论和建议后,我能够重构规范,现在覆盖率达到 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
如错误所述,您正在 yield
ing,但您没有提供块供其调用。
如果您的方法需要一个块,那么您需要在调用它时提供一个块。
为此,您需要更改此行:
described_class.stream_query_rows(sql_query)
像这样:
described_class.stream_query_rows(sql_query) { puts "this is a block" }