【问题标题】:rspec stub to allow [hash_key] to be passedrspec 存根以允许传递 [hash_key]
【发布时间】:2015-04-15 15:43:59
【问题描述】:

如何创建 rspec 方法存根以允许来自接受散列键的方法的响应以返回其值?

这是我要测试的行

sub_total = menu.menu_items[item] * quantity

我在 rspec 中使用这条线作为我的测试存根。

allow(menu).to receive(:menu_items[item]).and_return(2.0)

我的环境是用 ruby​​ 2.2.0 和 spec 3.1.7 设置的

但是我一直得到一个

NameError: undefined local variable or method `item'

Ruby 代码

def place_order(item, quantity, menu)
   sub_total = menu.menu_items[item] * quantity
   @customer_order << [item, quantity, sub_total]
 end

Rspec 代码

 let(:menu) { double :menu }

   it "should allow 1 order of beer to placed" do
     order = Order.new
     allow(menu).to receive(:menu_items[item]).and_return(2.0)
     order.place_order(:Beer, 1, 2.0)
     expect(order.customer_order).to eq [[:Beer, 1, 2.0]]
  end

失败:

  1) Order should allow 1 order of beer to placed
     Failure/Error: allow(menu).to receive(:menu_items[item]).and_return(2.0)
     NameError:
       undefined local variable or method `item' for #<RSpec::ExampleGroups::Order:0x007fbb62917ee8 @__memoized=nil>
     # ./spec/order_spec.rb:9:in `block (2 levels) in <top (required)>'

我尝试了很多方法,但没有任何效果

allow(menu).to receive(:menu_items).and_return(2.0)
allow(menu).to receive(:menu_items).with(item).and_return(2.0)
allow(menu).to receive(:menu_items).with("item").and_return(2.0)
allow(menu).to receive(:menu_items).with([item]).and_return(2.0)

我在 irb 中运行了我的代码,我可以看到它可以工作,但我找不到让我的班级双倍接收哈希键的方法。

【问题讨论】:

  • 似乎是一种脆弱的测试方法,但如果必须,让menu.menu_iterms 返回一些mock_menu_items 和存根mock_menu_items 以接收:[]item 并返回@987654333 @.

标签: ruby rspec


【解决方案1】:

menu.menu_items[item] 行实际上由 3 个方法调用组成。 [] 是对 menu_items 返回的 Hash 方法 [] 的调用。

我假设menu.menu_items 返回Hash 而不是Array,规范中给出的itemSymbol

这意味着您的存根需要更多的工作。

allow(menu).to receive(:menu_items).and_return({ Beer: 2.0 })

还要注意,错误

undefined local variable or method `item'

是因为您在规范中使用了item,但item 没有在您的方法之外定义。

【讨论】:

    【解决方案2】:

    你可以这样做:

    allow(menu.menu_items).to receive(:[]).and_return({Beer: 2.0})
    

    如果需要,您还可以传递特定项目:

    allow(menu.menu_items).to receive(:[]).with(1).and_return({Beer: 2.0})
    

    【讨论】:

      【解决方案3】:

      你的存根有点太深了,想想这个

      allow(menu).to receive(:menu_items).and_return({Beer: 2.0})
      

      【讨论】:

        【解决方案4】:

        感谢@SimoneCarletti 的回答,我能够轻松地存根PublicActivity 的实例。我添加这个答案只是作为对 OP 问题和解决方案简单性的更简短(重新)陈述。

        我想用存根模拟的代码:

        self.entity = activity.parameters['entity_string']
        

        并且测试的突出部分是双重的:

        activity = double('activity') # PublicActivity
        allow(activity).to receive(:parameters).and_return({'entity_string' => "some entity name"})
        

        完整代码:

        class ActivityRenderer
        
          attr_accessor :time
          attr_accessor :user
          attr_accessor :action
          attr_accessor :entity
        
          def initialize(activity)
            self.entity = activity.parameters['entity_string']
            self.time = activity.updated_at
            self.user = User.find(activity.owner_id)
            self.action = activity.key
          end
        end
        
        RSpec.describe ActivityRenderer do
          let(:user) { ...factory girl stuff... }
          let(:now) { Time.zone.now }
        
          before do
            Timecop.freeze
          end
        
          it 'provides an activity renderer' do
            activity = double('activity') # PublicActivity
            allow(activity).to receive(:parameters).and_return({'entity_string' => "some entity name"})
            allow(activity).to receive(:updated_at).and_return(now)
            allow(activity).to receive(:owner_id).and_return(user._id)
            allow(activity).to receive(:key).and_return('some activity?')
        
            ar = ActivityRenderer.new(activity)
        
            expect(ar.user).to eql(user)
            expect(ar.time).to eql(now)
            expect(ar.action).to eql('some activity?')
            expect(ar.entity).to eql("some entity name")
          end
        end
        

        【讨论】:

          猜你喜欢
          • 2019-03-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-26
          • 2014-02-08
          • 1970-01-01
          相关资源
          最近更新 更多