Nice programing

RSpec stubbed 메서드가 순서대로 다른 값을 반환 할 수 있습니까?

nicepro 2020. 11. 26. 19:53
반응형

RSpec stubbed 메서드가 순서대로 다른 값을 반환 할 수 있습니까?


다른 개체 인 Members locationlocation출력 을 병합 하는 메서드가있는 모델 Family가 있습니다. (구성원은 가족과 연결되어 있지만 여기서는 중요하지 않습니다.)

예를 들어, 주어진

  • member_1 has location== 'San Diego (여행 중, 5 월 15 일 반환)'
  • member_2에는 location== 'San Diego'가 있습니다.

Family.location이 'San Diego (member_1 여행 중, 5 월 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이 일련의 예제를 실행할 때 원래 클래스를 복원하지 않으므로 이러한 종류는 후속 예제를 "독"으로 덮어 씁니다.

그렇다면 스텁 메서드가 각 호출에서 다른 지정된 값을 반환하도록하는 방법이 있습니까?


호출 될 때마다 다른 값을 반환하도록 메서드를 스텁 할 수 있습니다.

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

따라서 처음 호출 @family.location할 때 'first'를 반환하고 두 번째로 'second'를 반환하고 이후에 호출 할 때마다 'other'를 반환합니다.


RSpec 3 구문 :

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

어떤 이유로 이전 구문을 사용하려는 경우에도 다음을 수행 할 수 있습니다.

@family.stub(:location).and_return('foo', 'bar')

허용 된 솔루션은 특정 수의 호출이 있고 특정 데이터 시퀀스가 ​​필요한 경우에만 사용해야합니다. 하지만 호출 할 호출 수를 모르거나 매번 다른 데이터의 순서신경 쓰지 않는다면 어떨까요? OP가 말했듯이 :

시퀀스에서 다른 값을 반환하는 것만으로도 괜찮습니다.

문제 and_return는 반환 값이 메모된다는 것입니다. 동적으로 반환하더라도 항상 동일한 결과를 얻을 수 있다는 의미입니다.

allow(mock).to receive(:method).and_return(SecureRandom.hex)
mock.method # => 7c01419e102238c6c1bd6cc5a1e25e1b
mock.method # => 7c01419e102238c6c1bd6cc5a1e25e1b

또는 실제 예는 공장을 사용하고 동일한 ID를 얻는 것입니다.

allow(Person).to receive(:create).and_return(build_stubbed(:person))
Person.create # => Person(id: 1)
Person.create # => Person(id: 1)

이러한 경우 매번 코드가 실행되도록 메서드 본문을 스텁 할 수 있습니다.

allow(Member).to receive(:location) do
  { residence: Faker::Address.city }
end
Member.location # => { residence: 'New York' }
Member.location # => { residence: 'Budapest' }

self이 컨텍스트 를 통해 Member 개체에 액세스 할 수 없지만 테스트 컨텍스트의 변수를 사용할 수 있습니다.

member = build(:member)
allow(member).to receive(:location) do
  { residence: Faker::Address.city, work: member.male? 'his_work' : 'her_work' }
end

위의 솔루션 개요를 시도했지만 내 기능이 작동하지 않습니다. 대체 구현으로 스터 빙하여 문제를 해결했습니다.

다음과 같은 것 :

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

참고 URL : https://stackoverflow.com/questions/5947999/can-rspec-stubbed-method-return-different-values-in-sequence

반응형