2011-09-02 2 views
0

Specs2 및 Mockito를 사용하여 일부 스칼라 코드를 시운전하려고합니다. 나는 세 가지 모두에 대해 비교적 새로운데, 조롱 한 메소드가 null을 반환하는 데 어려움을 겪고있다. 에서Scala, Specs2, Mockito 및 null 반환 값

(일부 이름 변경과 함께 전사) 나는 SUT의 번역기 호출을 추가하고, mockParser.parse 방법은 널 (null)을 반환했기 때문에 다음 죽을 때까지

"My Component's process(File)" should { 

    "pass file to Parser" in new modules { 
     val file = mock[File] 
     myComponent.process(file) 

     there was one(mockParser).parse(file) 
    } 

    "pass parse result to Translator" in new modules { 
     val file = mock[File] 
     val myType1 = mock[MyType1] 

     mockParser.parse(file) returns (Some(myType1)) 
     myComponent.process(file) 

     there was one(mockTranslator).translate(myType1) 
    } 

    } 

은 "파서에 패스 파일이"작동 다음 이것은 번역기 코드가 취할 수 없습니다.

비슷하게 SUT에서 번역 결과를 사용하려고 시도 할 때까지 "번역기로 전달 구문 분석 결과"가 전달됩니다.

이 두 가지 메소드에 대한 실제 코드는 결코 null을 반환 할 수 없지만 Mockito에게 예상 결과가 사용 가능한 결과를 반환하도록하는 방법을 알지 못합니다.

I 수있는 SUT에 널 (null) 검사를 넣어,하지만, 내가 널 대신 Option, NoneSome를 사용하여 반환하지 않습니다하십시오 만들고있어 오히려하지 않는 게 좋을으로하여이 주위의 코스 작업의. 좋은 스칼라/Specs2/Mockito 튜토리얼에

포인터로는 SUT 경우에 계속 실행을 허용 뭔가를 반환 할

there was one(mockParser).parse(file) 

같은 줄을 변경하는 방법에 대한 간단한 예는 것, 멋진 것 널 (null)을 처리하지 않습니다. 이 문제를 알아 내려고 노력에 대해 떨고

, 나는 내가 돌려 원하는 타입이다 myResult의 값으로

there was one(mockParser).parse(file) returns myResult 

에 그 라인을 변경 시도했다. 그게 내 반환 형식보다는 MatchResult을 찾을 것으로 예상대로 컴파일 오류를 줬어.

중요한 경우 스칼라 2.9.0을 사용하고 있습니다.

답변

3

본 적이 없으면 specs2 설명서의 mock expectation page을 볼 수 있습니다.

코드에서

, 스텁은

mockParser.parse(file) returns myResult이 돈의 편집 후 편집해야합니다 :

오해가 있었다. 당신이 당신의 두 번째 예제에서 그것을 할 방법은 좋은 일이고 당신은 첫 번째 테스트에서 동일해야한다 :

val file = mock[File] 
val myType1 = mock[MyType1] 

mockParser.parse(file) returns (Some(myType1)) 
myComponent.process(file) 
there was one(mockParser).parse(file) 

모의와 단위 테스트의 아이디어는 항상 동일합니다 : 당신의 모의 객체의 작동 방식 (설명 stubbing), 실행, 검증. 질문, 지금은 개인적인 조언을 대답해야

:

당신이 어떤 알고리즘 동작을 확인하려면 테스트 안 (첫번째 성공 과정을 역순으로 목록에 중지)를 제외하고, 대부분의 시간 단위 테스트에서의 기대.

예제에서 process 메서드는 "내용 번역"을 수행해야하므로 단위 테스트는 파서와 번역자를 조롱하고 스텁하여 전체 프로세스의 결과 만 확인해야합니다. 그것은 미세한 입자는 아니지만 단위 테스트의 목표는 방법의 모든 단계를 점검하는 것이 아닙니다. 구현을 변경하려면 메서드의 각 행을 확인하는 단위 테스트를 수정할 필요가 없습니다.

+0

두 번째 테스트에서는 스텁에서이 코드를 사용하지만 스텁보다는 예상치 못한 문제가 있습니다. 나는 명확히하기 위해 편집 할 것이다. –

+0

지금 편집을 완료했습니다. 링크 된 페이지도 살펴 보겠습니다. 나는 이전에 그것을 본 적이 있다고 생각하지만, 이전의 독서에 필수적인 단서를 놓쳤을 수도 있습니다. –

+0

그에 따라 대답을 편집했습니다 – Nicolas

0

전체가 없으면 말하기 어렵지만 모의하려는 방법이 최종 방법이 아닌지 확인해주세요. 이 경우 모키토는 모의 수 없으며 null을 반환합니다.

무언가가 작동하지 않으면 표준 JUnit 테스트에서 Mockito로 코드를 다시 작성해야합니다. 그런 다음 실패하면 질문에 Mockito 메일 링리스트의 누군가가 가장 잘 대답 할 것입니다.

+0

그것은 최종적인 것이 아닙니다. mock 및 스텁이 작동하며 테스트중인 코드에서 추가 된 null 검사로 테스트가 통과됩니다. –

1

나는 더 나은 해결책이 있을지 모르지만이를 해결할 수 있었기 때문에 내 자신의 답변을 올리 겠지만 즉시 받아 들일 수는 없습니다.

내가해야 할 일은 org.mockito.stubbing.Answer<T>의 형태로 모의 객체에 대해 합리적인 기본 반환 값을 제공하는 것이 었습니다. T는 반환 유형입니다.

나는 다음과 같은 모의 설정이 작업을 수행 할 수 있었다 :

val defaultParseResult = new Answer[Option[MyType1]] { 
    def answer(p1: InvocationOnMock): Option[MyType1] = None 
} 
val mockParser = org.mockito.Mockito.mock(implicitly[ClassManifest[Parser]].erasure, 
         defaultParseResult).asInstanceOf[Parser] 

org.specs2.mock.Mockito 특성과 호출 것들에 대한 소스의 검색을 조금 후.

이제는 null을 반환하는 대신 stubbed가 아닌 경우 (첫 번째 테스트에서 예상 한 경우 포함)을 반환하므로 테스트중인 코드에서이 값을 사용하여 테스트를 통과 할 수 있습니다.

mockParser 할당에서 엉망진창을 숨기는 테스트 지원 방법을 만들고, 여러 리턴 유형에 대해 동일한 기능이 필요하므로 여러 리턴 유형에 대해 동일한 작업을 수행 할 것입니다. 테스트.

org.specs2.mock.Mockito에서 더 짧은 방법에 대한 지원을 찾을 수는 없지만, 에릭이이를 추가하도록 유도 할 것입니다.

편집

소스의 추가 열람에 ... 대화에 저자가 반갑습니다, 내가 그냥 방법을 정의

def mock[T, A](implicit m: ClassManifest[T], a: org.mockito.stubbing.Answer[A]): T = org.mockito.Mockito.mock(implicitly[ClassManifest[T]].erasure, a).asInstanceOf[T] 

에게 전화를 할 수 있어야한다고 나에게 발생 org.specs2.mock.MockitoMocker에 있었는데 사실 위의 내 솔루션에 영감을주었습니다. 그러나 나는 그 전화를 알아낼 수 없다. mock은 오히려 과부하가 걸리므로 내 모든 시도가 다른 버전을 호출하고 내 매개 변수가 마음에 들지 않는 것처럼 보입니다.

에릭 에는이 이미 포함되어 있지만 그 방법을 이해할 수 없습니다.지금

def mock[T, A](implicit m: ClassManifest[T], default: A): T = { 
    org.mockito.Mockito.mock(
     implicitly[ClassManifest[T]].erasure, 
     new Answer[A] { 
     def answer(p1: InvocationOnMock): A = default 
    }).asInstanceOf[T] 
    } 

과 내가 설치 할 수있는 특성을 사용하여 내 모의

implicit val defaultParseResult = None 
val mockParser = mock[Parser,Option[MyType1]] 

으로 내가하지 : 나는 다음을 포함하는 특성을 정의

업데이트 결국이 특별한 테스트에서 이것의 사용법이 더 필요합니다. 사용 가능한 값을 제공하면 코드 테스트에서 null 검사없이 모든 테스트가 작동합니다. 어 시험. 그러나 다른 테스트에서 필요할 수 있습니다.

나는이 특성을 추가하지 않고이 문제를 처리하는 방법에 여전히 관심이 있습니다.

+0

최신 1.7-SNAPSHOT에서는 기본 대답을 포함하여 모든 유형의 모키토 설정을 전달할 가능성을 추가했습니다. 'val mockParser = mock [Parser] .defaultReturn (None)'보다 정교한 답이 있다면 다음과 같이 작성할 수 있습니다 :'val mockParser = mock [Parser] .defaultAnswer ((i : InvocationOnMock) => 뭐든지 (i))'. 설명서는 여기 [http://etorreborre.github.com/specs2/guide-SNAPSHOT/org.specs2.guide.Matchers.html#Mocks+creation+and+settings] – Eric

+0

에 있습니다. 나는 그것을 살펴볼 것이다. –