加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – RSpec 3:如何从我们尚未构建/添加的代码中存根方法和常

发布时间:2020-12-17 03:24:25 所属栏目:百科 来源:网络整理
导读:我们正在从我们构建的名为DBQuery的gem重构一个名为DataSourceIntegrations的 Ruby应用程序.我正在将一些DBQuery代码迁移到DataSourceIntegrations中.我正在构建的部分取决于DBQuery,它将在单独的步骤中添加. 同时,我需要编写RSpec测试来验证是否正确调用了D
我们正在从我们构建的名为DBQuery的gem重构一个名为DataSourceIntegrations的 Ruby应用程序.我正在将一些DBQuery代码迁移到DataSourceIntegrations中.我正在构建的部分取决于DBQuery,它将在单独的步骤中添加.

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

我有的是:

码-

宝石代码 –

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的方式存根.我的错误是:

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

我不知道为什么DBQuery :: Query被表示为模块,或者如何让它识别“new”.

解决方法

据我所知,您希望对DBQuery :: Query有所期望,而无需在代码中定义它. rspec-mocks可以 stub an undefined constant,就像你为DBQuery :: Query :: MAX所做的那样.要完全存根DBQuery :: Query,首先创建一个 class double并在测试中为它创建一个const:

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,1002])

您仍然需要存根嵌套常量,如DBQuery :: Query :: MAX

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

关于风格,我更喜欢放置存根并允许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',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,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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读