回答:
短い答えは、あなたの例では、結果はmock.method()
型に適切な空の値になるということです。mockitoは、プロキシー、メソッドインターセプト、およびMockingProgress
クラスの共有インスタンスを介した間接参照を使用して、モック上のメソッドの呼び出しが、スタブに関する情報を、モックメソッド。
mockitoコードを見て数分でミニ分析は次のとおりです。これは非常に大まかな説明です。多くの詳細がここにあります。githubのソースを自分でチェックすることをお勧めします。
まず、クラスのmock
メソッドを使用してクラスをモックすると、Mockito
基本的にこれが起こります。
Mockito.mock
代議員 org.mockito.internal.MockitoCore
.mockに、デフォルトのモック設定をパラメーターとして渡します。MockitoCore.mock
代議員 org.mockito.internal.util.MockUtil
.createMockデリゲートMockUtil
クラスには、使用ClassPathLoader
のインスタンスを取得するクラスをMockMaker
モックを作成するために使用するが。デフォルトでは、CgLibMockMakerクラスが使用されます。CgLibMockMaker
JMockから借用したクラスを使用してClassImposterizer
、モックの作成を処理します。使用「mockitoマジック」のキー片がされているMethodInterceptor
mockito:モック作成するために使用されるMethodInterceptorFilter
、とのインスタンスを含むMockHandlerインスタンスのチェーン、MockHandlerImplを。メソッドインターセプターは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フレームワークがどのように機能するかを理解したい人にとって、非常に優れたリソースです。
私の意見では、これはアンチパターンの典型的な使用法です。通常、メソッドを実装するときは「副作用」を回避する必要があります。つまり、メソッドは入力を受け入れて何らかの計算を行い、結果を返す必要があります。それ以外は何も変更されません。しかし、モッキトはわざとそのルールに違反しています。そのメソッドは、結果を返す以外に、Mockito.anyString()、mockInstance.method()、when()、thenReturnなどの一連の情報を格納します。これらはすべて特別な「副作用」があります。そのため、フレームワークは一見すると魔法のように見えます。通常、そのようなコードは記述しません。ただし、モックフレームワークの場合、このアンチパターンデザインは非常にシンプルなAPIにつながるため、優れたデザインです。