На примере нашего любимого калькулятора

class Calculator
  def add(a, b)
    a + b
  end

  def subtract(a, b)
    a - b
  end

  def multiply(a, b)
    a * b
  end

  def divide(a, b)
    raise ZeroDivisionError if b == 0
    a.to_f / b
  end
end
require 'rspec'
require_relative 'calculator'

RSpec.describe Calculator do
  let(:calculator) { Calculator.new }

  describe '#add' do
    it 'adds two numbers' do
      expect(calculator.add(2, 3)).to eq(5)
    end
  end

  describe 'mocking with receive' do

    it 'mocks the add method with allow' do
      allow(calculator).to receive(:add).with(2, 3).and_return(5)
      # Создает заглушку для метода add который для аргементов 2,3 вернет 5
      expect(calculator.add(2, 3)).to eq(5)
      # Ожидает что calculator.add(2, 3) вернет 5
    end

    it 'expects the add method to be called with expect' do
      expect(calculator).to receive(:add).with(2, 3).and_return(5)
      # Ожидаем что на объекте калькулятор будет вызван метод add с аргументами 2,3 и он вернет 5
      calculator.add(2, 3)
    end

  end
end