2011-05-10 2 views
50

У меня есть модель Семейство с методом location, которое объединяет выходы location других объектов, Участники. (Члены связаны с семьями, но это не важно.)Может ли RSpec закодированный метод возвращать разные значения в последовательности?

Например, при

  • member_1 имеет location == 'Сан-Диего (путешествия, возвращается 15 мая)'
  • member_2 имеет location == 'Сан-Диего'

Family.location может вернуться 'San Diego (member_1 travel, returns 15 May)' Специфика не имеет значения.

Чтобы упростить тестирование 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 запускает ряд примеров, он не восстанавливает исходный класс, поэтому этот вид переопределяет «яды» последующих примеров.

Итак, есть ли способ, чтобы зашитый метод возвращал разные, заданные значения для каждого вызова?

ответ

108

Вы можете заглушить метод для возврата разных значений каждый раз, когда он вызывается;

allow(@family).to receive(:location).and_return('first', 'second', 'other') 

Так первый раз, когда вы звоните @family.location он будет возвращать «первый», второй раз, когда он вернется «вторым», и все последующие разы вы называете его, он будут возвращать «другие».

+0

Спасибо за tip – apneadiving

+0

Спасибо, idlefingers! –

+0

Спасибо @idlefingers! Что делать, если вы хотите вернуть большое количество значений? –

0

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

Что-то вроде:

@family.stub(:location) { rand.to_s } 
12

RSpec 3 Синтаксис:

allow(@family).to receive(:location).and_return("abcdefg", "bcdefgh") 
0

Если по какой-то причине вы хотите использовать старый синтаксис, вы можете по-прежнему:

@family.stub(:location).and_return('foo', 'bar') 
Смежные вопросы