19

다음은 M Hartl의 Ruby on Rails 튜토리얼의 코드입니다. 누구든지 인스턴스 변수 (@user)가 필요한 이유와 왜 지역 변수를 사용하지 않는지 설명 할 수 있습니까? 또한 인스턴스 변수는 클래스의 인스턴스에있는 변수이기 때문에 어떤 클래스는 @user에서 인스턴스화 되었습니까? 그 상황에서 로컬 변수rspec의 인스턴스 변수는 어떻게 작동합니까?

require 'spec_helper' 

describe User do 

    before { @user = User.new(name: "Example User", email: "[email protected]") } 

    subject { @user } 

    it { should respond_to(:name) } 
    it { should respond_to(:email) } 
end 

답변

32

사용도 그 범위가 제한 before 때문에 오류가 발생 될 수 있음을 의미한다. @user은 User 유형이지만 describe 블록의 인스턴스 변수입니다. Rspec은 실행시에 각각의 describe 블럭을 만드는 마법을 가지고있다. 각 예 (it 블록)는 상기 클래스의 하위 클래스가됩니다. 클래스 상속을 통해 예제에 @user이 표시됩니다.

편집 2017년 5월 14일

링크 된 블로그 게시물은 더 이상 사용할 수 없습니다. Wayback Machine 링크로 업데이트 + 관련 섹션을 여기에서 인라인합니다.

이것은 blog post에 설명 된 바와 같이 반 패턴으로 간주됩니다. 대신 let을 사용하십시오.

let는 다음과 같은 장점을 갖는다 :

  • 일례 여러 번 사용할 때이 memoized 않고, 예 걸쳐 있지 .
  • 게으른로드이므로 변수를 참조하지 않는 예제를 초기화 할 때 시간을 낭비하지 않아도됩니다.
  • 변수 이름에 오타가있는 경우 예외가 발생합니다.
+1

오, 이제 알겠습니다.필자는 항상 블록이 사람에게 더 읽기 쉽도록 테스트를하기 위해 사용되었다는 것을 설명했습니다. 감사합니다 :) – TradeRaider

+0

해당 블로그 게시물을 더 이상 사용할 수 없습니다. 인스턴스 변수를 사용하여 반 패턴을 사용하고 끊어진 링크를 제거하는 이유를 포함하여 대답을 업데이트하는 것이 좋습니다. – keoghpe

2

subject ad it 블록이 다른 범위에 있으므로 로컬 변수가 작동하지 않습니다. @user은 RSpec이 생성 한 클래스에 속합니다.

12

로컬 변수는 로컬 메소드의 범위에만 존재하기 때문에 로컬 변수를 사용할 수 없습니다. before, subjectit은 동일한 클래스 내에서 다른 범위를 생성합니다.

before { user = User.new(name: "Example User", email: "[email protected]") } 

당신이

subject { user } 

인스턴스 @user에 전화를 정의되지 않은 변수를 올릴 것이다 다음 코드는 User (결국 클래스의 인스턴스, 당신은 User.new 함께 만들).

그러나 인스턴스 변수 대신 let 명령을 사용할 수 있습니다. 또한 정의 할 경우

subject { User.new(name: "Example User", email: "[email protected]") } 

before을 사용할 필요가 없습니다. subject 메서드를 사용하여 인스턴스에 액세스 할 수있는 추가 이점을 얻을 수도 있습니다. 정의는 let(:subject)입니다.

+4

+1 : let (: user) {User.create (name : "예제 사용자", email : "[email protected]")}' – Meltemi

+0

+1 사용 주제 : subject {사용자. 새로운 (이름 : "Example User", 이메일 : "[email protected]")} –