4

お気に入りの Java/JavaScript Mocktito ライブラリを Smalltalk に移植しています。私は現在、実際のオブジェクトをスタブ化するために Spy を実装する段階にあります。私の問題は、スパイされたオブジェクトがスタブ化された独自のメソッドを呼び出すときに発生します。それ以外の:

self aMethod.

私はスパイオブジェクトへの呼び出しを委譲したいと思います:

spyObject aMethod.

予想される動作のシナリオ テストを次に示します。

realObject := RealObjectForTesting new.
spyedObject := Spy new: realObject.
spyedObject when: #accesorWhichReturnsValue thenReturn: 'stubbed value'.

spyedObject accesorWhichCallsSelf.

self assert: (spyedObject verify: #accesorWhichReturnsValue).

なにか提案を?

4

3 に答える 3

3

ObjectsAsMethodsWrapperライブラリを使用して、を直接ラップすることができRealObjectUnderTestます。これは、いくつかの便利な事前定義されたラッパーとともに、ラッパーをインストールおよび削除するための便利なAPIを提供します。CompiledMethod

ラッパーは実オブジェクトのメソッドディクショナリにインストールされているため、これらは自己送信をインターセプトします。したがって、メッセージを基になるに渡す前に、メッセージに任意の変更を実行する可能性がありますCompiledMethod

私の例は、ソースコードに触れることなくメソッド呼び出しをメモ化する方法を示していますが、メソッド呼び出しをモックアウトするために必要な基本的な知識を提供するはずです。

この特定の手法には制限があります。クラス自体が定義するメッセージへの自己送信をインターセプトします。したがって、FooサブクラスBarを作成してラッパーをにインストールした場合、のプロトコルのFoo一部を形成するメッセージをインターセプトすることはありませんBar(もちろんそれらもラップしない限り)。

SqueakまたはPharoイメージ(およびおそらくGNU Smalltalkでも)で、または同様のメッセージをインターセプトすることはできません。これらはメッセージ送信ではないためです。コンパイル時の変換は、これらのメッセージ送信をジャンプバイトコードにインライン化します。(メッセージ送信の錯覚は、バイトコードを変換解除する方法などを知っているため、比較的説得力があります。)ifTrue:ifFalse:timesRepeatDecompilerifTrue:ifFalse:

于 2012-11-01T19:17:58.983 に答える
3

「スパイ」を実装のみの「ラッパー」オブジェクトにしてdoesNotUnderstand:から、 を使用して実際のオブジェクトと交換しますbecome:

スパイのdoesNotUnderstand:メソッドはすべてのメッセージに対して呼び出され、たとえばその引数 (Message オブジェクト) をログに記録して元のオブジェクトに送信できます。

Smalltalk イメージでの実装者を参照するとdoesNotUnderstand:、いくつかの例を見つけることができます (たとえば、Squeak にはMessageCatcherとがありObjectViewerます)。

于 2012-10-31T15:38:08.593 に答える
2

Smalltalk には、自分自身への送信を傍受する組み込みのメカニズムがないため、風変わりな手段に頼る必要があります。

おそらく最も簡単な方法は、元のオブジェクトからメソッドを動的に盗むことです。バートが示唆するように、スパイは #become: を使用してターゲットを置き換えます。次に、スパイがメッセージを受信すると、メッセージを元のオブジェクトに転送する代わりに、そのクラスでセレクターを検索し、スパイを受信者として実行します。コンパイルされたメソッドを任意の受信者に対して実行するメカニズムは、方言によって異なります。Squeak では CompiledMethod class>>receiver:withArguments:executeMethod: です。

先ほど述べたように、これは非常に風変わりです。スパイの作成時にスパイのカスタム クラスを生成し、コンパイルされたメソッドが新しいレシーバーで正しく動作するように、ターゲット オブジェクトと同じ構造を持つようにする必要があります。また、ターゲットの状態をスパイにコピーし、スパイが完了したら元のオブジェクトに戻す必要があります。最後に、スパイの状態がターゲットの状態と一致する必要があるため、ターゲットを隠しておく場所を見つける必要があります。それはすべて実行可能ですが、単純ではありません。クラスとメソッドを動的に生成しますが、これにはシステムの低レベルの理解が必要です。

于 2012-10-31T17:31:19.877 に答える