Rspec: Как проверить рекурсию? - PullRequest
8 голосов
/ 02 сентября 2010

Я хотел бы проверить, что метод вызывается рекурсивно с определенным аргументом.

Мой подход:

class Recursable
  def rec(arg)
    rec(7) unless arg == 7
  end
end

describe Recursable do
  it "should recurse" do
    r = Recursable.new('test')
    r.should_receive(:rec).with(0).ordered
    r.should_receive(:rec).with(7).ordered
    r.rec(0)
  end
end

Неожиданно сбой RSpec с:

expected :rec with (7) once, but received it 0 times

Есть идеи, что случилось с моим подходом? Как проверить эффективную рекурсию с определенным аргументом?

Ответы [ 2 ]

10 голосов
/ 02 сентября 2010

Проблема с вашим тестом, как сейчас, заключается в том, что вы отбрасываете метод, который пытаетесь протестировать.r.should_receive(:rec) заменяет r#rec заглушкой, которая, конечно, никогда не вызывает r.rec(7).

Лучшим подходом было бы просто проверить, что результат первоначального вызова метода верен.Строго не важно, будет ли метод повторять, повторять или вызывать друга, если он в конце дает правильный ответ.

2 голосов
/ 02 июля 2013

Часто, если вам нужно протестировать рекурсию, это - запах кода;вам, вероятно, следует разделить метод на разные обязанности или что-то в этом роде.

Но иногда вам просто нужно добавить некоторые базовые проверки вашей рекурсии.Вы можете сделать это с помощью Rspec and_call_original:

it "should recurse" do
  r = Recursable.new('test')
  r.should_receive(:rec).with(0).ordered.and_call_original
  r.should_receive(:rec).with(7).ordered.and_call_original
  r.rec(0)
end

Обычно should_receive просто заглушает реальный метод, поэтому рекурсия не работает.При and_call_original метод-заглушка (содержащий тестовые проверки) также будет вызывать исходную реализацию метода, которая будет выполнять рекурсию, как и ожидалось.

...