답변:
짧은 대답은 귀하의 예에서의 결과가 mock.method()
유형에 적합한 빈 값이 될 것이라는 것입니다. mockito는 MockingProgress
mock에 대한 메서드 호출이 스터 빙에 대한 정보를 반환 값을 통해 전달하는 대신 스터 빙 또는 기존 스터 빙 동작의 재생을위한 것인지 여부를 결정하기 위해 프록시, 메서드 인터 셉션 및 클래스 의 공유 인스턴스를 통한 간접 지정을 사용 합니다. 모의 방법.
mockito 코드를 살펴 보는 몇 분의 미니 분석은 다음과 같습니다. 이것은 매우 대략적인 설명입니다. 여기에 많은 세부 사항이 있습니다. github 의 소스를 직접 확인하는 것이 좋습니다 .
첫째, 클래스의 mock
메서드를 사용하여 클래스를 모의하면 다음 과 같은 Mockito
일이 발생합니다.
Mockito.mock
org.mockito.internal.MockitoCore
.mock에 위임 하여 기본 모의 설정을 매개 변수로 전달합니다.MockitoCore.mock
org.mockito.internal.util.MockUtil
.createMock에 위임MockUtil
클래스는 사용 ClassPathLoader
의 예를 얻을 클래스를 MockMaker
모의을 만드는 데 사용합니다. 기본적으로 CgLibMockMaker 클래스가 사용됩니다.CgLibMockMaker
ClassImposterizer
모의 생성을 처리하는 JMock에서 빌린 클래스를 사용합니다 . 사용 된 'mockito 마법'의 주요 부분이있다 MethodInterceptor
mockito : 모의 만드는 데 사용 MethodInterceptorFilter
, 그리고 인스턴스를 포함 MockHandler 인스턴스의 사슬 MockHandlerImpl을 . 메소드 인터셉터는 MockHandlerImpl 인스턴스에 호출을 전달합니다.이 인스턴스는 메소드가 모의 객체에서 호출 될 때 적용되어야하는 비즈니스 로직을 구현합니다 (즉, 응답이 이미 기록되어 있는지 검색, 호출이 새 스텁을 나타내는 지 확인하는 등). 기본 상태는 호출되는 메소드에 대해 스텁이 아직 등록되지 않은 경우 유형에 적합한 빈 값이 리턴되는 것입니다.이제 예제의 코드를 살펴 보겠습니다.
when(mock.method()).thenReturn(someValue)
이 코드가 실행되는 순서는 다음과 같습니다.
mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn
무슨 일이 일어나고 있는지 이해하는 열쇠는 모의 메서드가 호출 될 때 일어나는 일입니다. 메서드 인터셉터는 메서드 호출에 대한 정보를 전달하고 MockHandler
인스턴스 체인에 위임하여 결국 MockHandlerImpl#handle
. 동안 MockHandlerImpl#handle
, 모의 핸들러의 인스턴스를 생성 OngoingStubbingImpl
및 공유에 전달 MockingProgress
인스턴스입니다.
를 when
호출 한 후 메서드가 호출 되면 동일한 클래스 의 메서드 를 호출하는에 method()
위임됩니다 . 이 메서드 는 모의 호출이 쓴 공유 인스턴스 에서 진행중인 스터 빙을 풀고 이를 반환합니다. 그런 다음 인스턴스 에서 메서드가 호출됩니다 .MockitoCore.when
stub()
MockingProgress
method()
thenReturn
OngoingStubbing
when(mock.method()).thenXyz(...)
구문을 사용하면 mock.method()
"스터 빙"모드가 아닌 "재생"모드에서 실행됩니다. 일반적으로, 이러한 실행이 mock.method()
때문에 나중에 때 아무런 영향을 미치지 않는다 thenXyz(...)
( thenReturn
, thenThrow
, thenAnswer
등)를 실행 얻는다는 모드 "스텁"로 전환하고 그 메소드 호출에 대한 원하는 결과를 기록한다.
짧은 대답은이면에서 Mockito는 일종의 전역 변수 / 저장소를 사용하여 메서드 스텁 빌드 단계 (예제에서 method (), when (), thenReturn () 호출) 정보를 저장하므로 결국 어떤 매개 변수에서 무엇을 호출 할 때 반환되어야 하는지를지도를 작성합니다.
이 기사가 매우 유용하다는 것을 알았습니다. 프록시 기반 모의 프레임 워크 작동 방식 설명 ( http://blog.rseiler.at/2014/06/explanation-how-proxy-based-mock.html ). 저자는 데모 Mocking 프레임 워크를 구현했으며, 이러한 Mocking 프레임 워크의 작동 방식을 파악하려는 사람들에게 매우 좋은 리소스를 찾았습니다.
제 생각에는 Anti-Pattern의 전형적인 사용법입니다. 일반적으로 메서드를 구현할 때 '부작용'을 피해야합니다. 즉, 메서드가 입력을 받아 계산을 수행하고 결과를 반환해야합니다. 그 외에 다른 변경 사항은 없습니다. 그러나 Mockito는 의도적으로 그 규칙을 위반합니다. 그 메서드는 결과를 반환하는 것 외에도 많은 정보를 저장합니다 : Mockito.anyString (), mockInstance.method (), when (), thenReturn, 모두 특별한 '부작용'이 있습니다. 이것이 프레임 워크가 언뜻보기에 마법처럼 보이는 이유이기도합니다. 우리는 보통 그런 코드를 작성하지 않습니다. 그러나 모의 프레임 워크의 경우이 안티 패턴 디자인은 매우 간단한 API로 이어지기 때문에 훌륭한 디자인입니다.