2010-09-01 4 views
7

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

Мой подход:

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 

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

ответ

10

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

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

+0

А, ладно. Ну что ж! Я пытаюсь найти ошибку - метод возвращает неправильное значение (это сложнее, чем показано здесь). Я думал, что смогу проверить каждую его часть, чтобы сузить пространство проблем. Это усложняется с каждым уровнем рекурсии, и было бы неплохо проверить, правильно ли выполняется рекурсия. – crispy

+2

Другими словами: Не тестируйте реализацию, проверяйте эффект, который имеет код. Отличный ответ! – awendt

2

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

Но несколько раз вам просто нужно добавить некоторые основные проверки на вашу рекурсию. Вы можете сделать это с 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 зашитый метод (содержащий тестовые проверки) также вызовет реализацию исходного метода, который будет выполнять рекурсию, как ожидалось.

Смежные вопросы