Rspec matcher to test a method calls another inside an each block

Viewed 159

I'm trying to test that a ruby method calls another method from inside it, in an each block

Sample classes

class A
  def foo
    return 'foo'
  end
end

class B
  def initialize
    @array_of_class_a_instances = []
  end

  def bar
    @array_of_class_a_instances.each do |element|
      element.foo
    end
  end
end

I want to write a unit test for the bar method inside the B class to verify that the foo method is being called for the amount of times that @array_of_class_a_instances is long. If we say that the array has 4 elements, I want to test that the foo method is being called 4 times. I have a test that works below, but it uses multiple expect statements. Is there some syntax where it could be written with just one?

describe B do
  describe '#bar' do
    # ommitted for brevity
    small_b = B.new
    it 'calls the foo method for each element in the array' do
      expect(small_b.array_of_class_a_instances[0]).to receive(:foo).exactly(1).time
      expect(small_b.array_of_class_a_instances[1]).to receive(:foo).exactly(1).time
      expect(small_b.array_of_class_a_instances[2]).to receive(:foo).exactly(1).time
      expect(small_b.array_of_class_a_instances[3]).to receive(:foo).exactly(1).time
      small_b.bar
    end
  end
end
1 Answers

You can use each in your test as well:

small_b.array_of_class_a_instances.each do |instance|
  expect(instance).to receive(:foo).exactly(1).time
end

You can also use the all matcher to check all elements of an array at once.

expect(small_b.array_of_class_a_instances).to all(receive(:foo).exactly(1).time)
Related