Может ли RSpec заштрихованный метод возвращать разные значения в последовательности?
У меня есть модель Family с методом location
, который объединяет выходы location
других объектов, Members. (Члены связаны с семьями, но это не важно здесь.)
Например, данный
- member_1 имеет
location
== 'Сан-Диего (путешествие, возвращается 15 мая)'
- member_2 имеет
location
== 'Сан-Диего'
Family.location может вернуться 'San Diego (member_1 travel, возвращается 15 мая)' Специфика несущественна.
Чтобы упростить тестирование Family.location, я хочу заглушить Member.location. Однако мне нужно вернуть два разных (указанных) значения, как в приведенном выше примере. В идеальном случае они были бы основаны на атрибуте member
, но простое возвращение разных значений в последовательности было бы в порядке. Есть ли способ сделать это в RSpec?
В каждом примере тестирования можно переопределить метод Member.location, например
it "when residence is the same" do
class Member
def location
return {:residence=>'Home', :work=>'his_work'} if self.male?
return {:residence=>'Home', :work=>'her_work'}
end
end
@family.location[:residence].should == 'Home'
end
но я сомневаюсь, что это хорошая практика. В любом случае, когда RSpec запускает ряд примеров, он не восстанавливает исходный класс, поэтому этот вид переопределяет "яды" последующих примеров.
Итак, есть ли способ, чтобы зашитый метод возвращал разные, заданные значения для каждого вызова?
Ответы
Ответ 1
Вы можете заглушить метод, чтобы возвращать разные значения каждый раз, когда он вызывал;
allow(@family).to receive(:location).and_return('first', 'second', 'other')
Итак, в первый раз, когда вы вызываете @family.location
, он вернет "первый", второй раз вернет "второй", и все последующие раз, когда вы его вызываете, он вернет "другое".
Ответ 2
Синтаксис RSpec 3:
allow(@family).to receive(:location).and_return("abcdefg", "bcdefgh")
Ответ 3
Я пробовал контур решения выше, но он не работает для моего. Я решил проблему, выполнив замену.
Что-то вроде:
@family.stub(:location) { rand.to_s }
Ответ 4
Если по какой-то причине вы хотите использовать старый синтаксис, вы все равно можете:
@family.stub(:location).and_return('foo', 'bar')