2014-05-23 3 views
1

레일스에서 ​​서비스 오브젝트 클래스를 테스트하는 방법에 대해 궁금합니다. 사용자가 가입한다고 가정 해 보겠습니다. 사용자가 데이터베이스에서 생성되고 전자 메일 목록에 추가되며 다른 일이 발생합니다. 이걸 어떻게 시험해?서비스 클래스 테스트 - 레일

class UserRegistrar 
    def sign_up(user) 
    User.create(user) # or something to this effect 
    EmailMarketing.add_to_email_list(user) 
    SuperSecretClass.do_secret_stuff(user) 
    LoggingThing.new.log_stuff_about(user) 
    end 
end 

(컨트롤러 액션)

def create 
    UserRegistrar.sign_up(params) 
    # stuff for the strong params, etc... 
end 

난 그냥 방법이 올바른 인수라고되어 있는지 확인하는 것입니다 무엇. 메소드의 결과 (사용자가 실제로 목록에 추가되는지 확인하는 것과 같음)는 각각의 클래스에서 테스트됩니다. 내가 제대로하고 있니?

답변

1

당신이 말하는 방식대로하십시오. 예제에서 모든 작업은 고유 한 테스트가 필요하고 둘 이상의 장소에서 사용될 수있는 고급 모델 메서드에 위임되므로 테스트의 테스트에서 해당 메서드의 기능을 테스트하는 것이 타당하지 않습니다. 서비스. 그리고 모의 메소드 호출이 많지 않으므로 너무 고통스럽지 않습니다.

그러나

, 그 모델의 방법 중 하나는 하나 개의 서비스에 사용 된 경우

  • , 나는 모델 다운 슬림에 서비스로 사람들을 이동하는 것을 고려하고 서비스가 더 일관된 만들 것입니다. 만약 위임을하기보다 스스로 많은 일을했던 서비스의 메소드가 생기면, 서비스의 테스트, 데이터베이스 객체 생성, 서비스 변경 방법에 대한 테스트 등의 기능을 테스트 할 것입니다.

  • 다른 한편으로는 위임 된 서비스 만있는 경우 BDD를 수행하고 수락 테스트를 먼저 작성하기 때문에 수락 테스트에서 이미 충분히 테스트했을 수 있습니다. 서비스를 단위 테스트하십시오.

+0

두 번째 사항에 동의합니다. 사실 나는 "메소드를 호출해야한다"(사용자가 만들어 졌는지, 사용자가 메일 링리스트에 추가되었는지)와 대조적으로 수락 테스트 만한다고 생각하고 있습니다. "내가이 방법을 호출 했는가"는 많은 가치가없는 것 같습니다 (무언가가 변경되었는지 확인하기 위해 무언가가 호출되었는지 확인). –

+0

오른쪽, 메서드 호출 기대 값은 본질적인 값이 없습니다. 그것들은 테스트하기에는 비실용적 인 상태 변화를 시험하는 것만으로 충분합니다. –

1

테스트에서 모든 것을 스터핑하는 것은 위험합니다. 코드의 나머지 부분에 맞추는 대신 클래스가 테스트에 맞는지 테스트하기 때문입니다. EmailMarketing.add_to_email_list 리팩토링에서 하루가 EmailMarketing.add_to(:email_list ...)이되면 테스트를 수행하지 못할 것입니다.

당신은 예를 들어 User를 사용하여,이 같은 코드의 효과를 테스트 할 수 있습니다

expect { 
    UserRegistrar.sign_up(user) 
}.to change{ 
    user.persisted? 
}.from(false).to(true) 
나는 당신이 보여주는 것과 같은 클래스의 단위 테스트를 작성하기 위해 필요한 경우 예, 나는 좋겠
+0

흠 이제 수업이 시험에 결합 된 것처럼 보입니다. 그러나 시험과 결합 된 수업이 아닌가? 그런 수업을 어떻게 시험하겠습니까? –

+0

나는 사용자가 저장되었는지, 전자 메일 목록에 추가되었는지, 게시 된 비밀, 기록 된 로그 등의 여부에 관계없이 메서드의 최종 결과를 테스트합니다. 목표는 실제 요구 사항이 충족되지 않을 때마다 테스트를 실패하게 만드는 것입니다. – jimworm