rubyrspechashmapmocking

Ruby and Rspec mocking a hash


I have created a method which adds up all the value pairs in a hash. The method works but am struggling to mock a test for it.

Here is the method,

class Basket

  attr_reader :order, :total

  def initialize
    @order = {}
    @total = total
  end

  def add
    @total = (@order.map { |x,y| y}).sum.round(10)
  end
end

And the test, with my attempt at mocking the hash.

order = {"pizza" => 12.99}
let(:basket) { double(order: order, total: nil, add: nil)}

describe '#add' do
    it 'calculates the total price for an order' do
      basket.add
      expect(basket.total).to eq 12.99
    end
  end

And the fail message.

expected: 12.99
     got: nil

(compared using ==)

Like I mentioned, the method in the class is working. Just need my test to pass! Any help would be great.


Solution

  • I think you are looking for a partial double to stub certain features while allow this object to still function as normal.

    Similar to the following:

    class Basket
      attr_reader :order, :total
      def initialize
        @order = {}
      end
      def add
        @total = order.map { |_,y| y}.sum # note no @ in front of order
      end
    end
    
    RSpec.describe Basket do 
    
      let(:order)  { {"pizza" => 12.99} }
      let(:basket) { Basket.new}
    
      describe '#add' do
        it 'calculates the total price for an order' do
          allow(basket).to receive(:order).and_return(order)
          basket.add # we have to call add or total will be nil
          expect(basket.total).to eq 12.99
        end
      end
    end
    

    Here we use a real Basket but when that basket calls #order we stub the response.

    There is a sizable amount of other clean up to be done since there is no way to put an order in a basket right now and if you do not call #add then total will be nil even with an order