whenNew
の仕組みを理解するために2つのクラスがあります。powermockitoは新しいインスタンスをどのように傍受するのですか?
public class RockService {
public RockData serv() {
RockData rockData = new RockData();
rockData.setName("RockService");
rockData.setContent("content from rock service");
return rockData;
} }
そして
public class RockData {
String name;
long id;
String content;
// get set method ignored
}
テストコード付き
@RunWith(PowerMockRunner.class)
@PrepareForTest(RockService.class)
public class MockNewInstanceCreation {
@Test
public void mockCreationTest() throws Exception {
RockData rockData = mock(RockData.class);
when(rockData.getName()).thenReturn("this is mock");
whenNew(RockData.class).withNoArguments().thenReturn(rockData);
RockService rockService = new RockService();
RockData servData = rockService.serv();
System.out.println(servData.getName());
System.out.println(servData.getContent());
}
}
モックないのであれば、実行時に、出力(RockData's getName())
は "RockService" になります。しかし、モックでは、これは "これはモック"を返します。コードは機能しますが、まだ私はPowermock/Mockitoがこれをどう正確に行ったか分かりませんでした。
コードをデバッグしました。私が混乱したのはRockData rockData = new RockData();
が実行された後で、実際にはRockData rockData = mock(RockData.class);
によって作成されたインスタンスです。つまり、new RockData()
は新しいインスタンスをまったく作成しません。すでに作成したインスタンスが返されたばかりです。デバッグすると、MockGateway.newInstanceCall
にジャンプしました。
したがって、Powermockitoはどのように新しいインスタンスをインターセプトしますか?
:
は、以下のコードを参照してください。 Mockフレームワークは、バイトコードgenとクラスローダーを使用してターゲットクラスをモックします。私の場合はRockDataです。私を混乱させるのは、インスタンスを作成するコードです。ここに私の場合、RockServiceがあります。 RockService.servで、 "RockData rockData = new RockData();"新しいインスタンスを作成します。どうすれば "RockData rockData = mock(RockData.class);"と同じインスタンスになりますか? Mockitoは "新しい"操作をハッキングしましたか?既存のインスタンスを作成するのではなく、既存のインスタンスを返しますか? String.intern()と同じですか?または、mockitoもRockServiceのバイトコードを変更しますか? – DeepNightTwo
@PrepareForTest(RockData.class)ではなく、ケースを実行するために@PrepareForTest(RockService.class)を追加する必要があります。だから@PrepareForTestは何ですか? – DeepNightTwo
PowerMockitoはRockServiceのバイトコードを変更しません。 @PrepareForTest(RockService.class)は、RockServiceクラス内で "ハッキングされた"クラスローダーを使用する必要があることをMockitoに伝えます。このアノテーションがなければ、標準的なJavaクラスローダーを使用しますので、RockDataのモックを返すことはできません。 whenNewArguments()。thenReturn(rockData); whenNew(RockData.class).withNoArguments()。 Mockitoに特別なクラスローダーを準備するように指示し、PrepareForTest注釈は、それがどこで使用されるべきか、 –