Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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')