gpt4 book ai didi

ruby - RSpec 3 : How to stub methods and constants from code we have yet to build/add?

转载 作者:数据小太阳 更新时间:2023-10-29 07:15:09 24 4
gpt4 key购买 nike

我们正在从我们构建的名为 DBQuery 的 gem 中重构一个名为 DataSourceIntegrations 的 Ruby 应用程序。我正在将一些 DBQuery 代码迁移到 DataSourceIntegrations 中。我正在构建的部分取决于 DBQuery,它将在单独的步骤中添加。

与此同时,我需要编写 RSpec 测试来验证 DBQuery 代码是否被正确调用,所有这些都没有 DBQuery。

我有的是:

代码—

gem 密码—

module DBQuery
class Query
MAX = 1000

def retrieve_users
# Returns an array of user IDs
end
end
end

应用程序代码—

  module Integration
def initialize
@query = DBQuery::Query.new
end
end

module Integration
class StackOverflowIntegration
include Integration

def query
users = []
while (users < DBQuery::Query::MAX) do
# Creates a users buffer
users.push @query.retrieve_users(users_buffer)
end
end
end
end

测试—

describe Integration::StackOverflowIntegration do
let(:db_query) { double('DBQuery::Query') }

before do
stub_const('DBQuery::Query::MAX', 1000)
allow(db_query).to receive(:new).and_return(db_query)
allow(db_query).to receive(:retrieve_users).and_return([1000, 1001, 1002])
end

it 'queries without error' do
expect { StackOverflowIntegration.new.query }.to_not raise_error
end
end

我不知道如何以不需要 DBQuery 的方式 stub 。我的错误是:

NoMethodError:
undefined method `new' for #<Module:0x007fa7ce561968>

我不知道为什么 DBQuery::Query 被表示为一个模块,或者如何让它识别"new"。

最佳答案

据我了解,您想对 DBQuery::Query 做出期望,而不是在您的代码中定义它。 rspec-mocks 可以 stub an undefined constant ,就像您对 DBQuery::Query::MAX 所做的一样。要完全 stub DBQuery::Query,请创建一个 class double首先在你的测试中为它 stub 一个常量:

db_query__query_class = class_double('DBQuery::Query')
stub_const('DBQuery::Query', db_query__query_class)

这样,您代码中的 DBQuery::Query 将返回 query_class double。然后你可以用它定义一些行为:

query_instance = instance_double('DBQuery::Query')
allow(db_query__query_class).to receive(:new).and_return(query_instance)
allow(db_query).to receive(:retrieve_users).and_return([1000, 1001, 1002])

您仍然需要 stub 嵌套常量,例如 DBQuery::Query::MAX

stub_const('DBQuery::Query::MAX', 1000)

关于样式,我更喜欢将 stub 和允许放在 let/let! 语句中,如下所示:

describe Integration::StackOverflowIntegration do
let!(:db_query__query_class) do
class_double('DBQuery::Query').tap do |double|
stub_const('DBQuery::Query', double)
stub_const('DBQuery::Query::MAX', 1000)
allow(double).to receive(:new).and_return(query_instance)
end
end
let(:query_instance) do
instance_double('DBQuery::Query').tap do |double|
allow(double).to receive(:retrieve_users).and_return([1000, 10001, 1002])
end
end
end

我还喜欢将返回值放在它们自己的 let 中,这样我就可以轻松更改它们。这是一个完整的工作(和虚拟)示例:

RSpec.configure do |c|
c.around(:context, :protect_with_timeout) do |example|
Timeout::timeout(2) {
example.run
}
end
end

describe Integration::StackOverflowIntegration do
let!(:db_query__query_class) do
class_double('DBQuery::Query').tap do |double|
stub_const('DBQuery::Query', double)
stub_const('DBQuery::Query::MAX', max_queries)
allow(double).to receive(:new).and_return(query_instance)
end
end
let(:query_instance) do
instance_double('DBQuery::Query').tap do |double|
allow(double).to receive(:retrieve_users).and_return(retrieved_users)
end
end
let(:max_queries) { 1000 }
let(:retrieved_users) { [1000, 1001, 1002] }

describe '#query' do
subject(:stack_overflow_query) { Integration::StackOverflowIntegration.new.query }

it 'queries without error in nominal case' do
expect { stack_overflow_query }.to_not raise_error
end

context 'with 0 users returned' do
let(:retrieved_users) { [] }

it 'does not loop forever', :protect_with_timeout do
pending('not implemented yet...')
stack_overflow_query # will timeout
end
end

context 'with 10 users returned' do
let(:retrieved_users) { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }

it 'calls #retrieve_users 100 times' do
stack_overflow_query
expect(query_instance).to have_received(:retrieve_users).exactly(100).times
end
end

context 'with DBQuery::Query::MAX set to 0' do
let(:max_queries) { 0 }

it 'does not call #retrieve_users at all' do
stack_overflow_query
expect(query_instance).not_to have_received(:retrieve_users)
end
end
end
end

关于ruby - RSpec 3 : How to stub methods and constants from code we have yet to build/add?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29111573/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com