2016-02-19 47 views
5

PowerMockitoを使用して、私がテストしているコードでjava.net.URLクラスを作成しようとしています。基本的には、実際のHTTPリクエストが発生するのを防ぎ、その代わりに1)リクエストが行われたときにデータをチェックし、2)擬似レスポンスで自分のテストデータを返す必要があります。これは私がしようとしているものです:PowerMockito/Mockitoを使用してURLクラスをモックできません

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ URL.class, MockedHttpConnection.class }) 
public class Test { 
    URL mockedURL = PowerMockito.mock(URL.class); 
    MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class); 

... 
    PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL); 
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection); 

... 
} 

私がテストしたいコードは次のようになります。私は「MyURLString」と一致するwlInvokeUrlStringを模擬

以前の私のテストシナリオで
URL wlInvokeUrl = new URL(wlInvokeUrlString); 
connection = (HttpURLConnection) wlInvokeUrl.openConnection(); 

。私はまた、さまざまな他の形式のwhenNew行を使って、モックを注入しようとしました。私が何を試みても、コンストラクタを傍受することは決してありません。私がしたいのは、openConnection()の呼び出しを「キャッチ」して、本当のHTTP接続ではなく虚偽のHTTP接続を返すことだけです。

私は同じスクリプトの中でこのクラスより先に他のクラスを嘲笑しましたが、これらは期待どおりに動作しています。私は目の第二のペア(おそらく真)が必要か、URLクラスに関して独特の何かがあります。私は "whenNew(URL.class).withAnyArguments()"を使用し、 "thenReturn"を "thenAnswer"に変更すると、トリガーすることができることに気付きました。唯一の問題は私のコードのURL呼び出しを取得しないことです。私が見ているのは、URL.classの3引数コンストラクタの呼び出しで、すべてのパラメータがnullであることです。このクラスはJavaランタイムのもので、テストランナーがブートストラップしていますか?どんな助けでも大歓迎です。

+0

これをテストするにはPowermockは必要ありません。例として、ファイルベースのパス( "file://my-test.properties")を使用するには、文字列urlをモックしてください。これはうまくいくでしょうし、必要なデータを渡すことができます –

+0

@JérémieBもう少し詳しく説明できますか?これは、エレガントでシンプルなソリューションのようですが、テスト対象のコードはHttpURLConnectionを期待しています。ファイルを参照するURL文字列を変更するとClassCastExceptionが発生します(例:java.lang.ClassCastException:sun.net.www.protocol。 ftp.FtpURLConnectionはjava.net.HttpURLConnectionにキャストできません)。また、このアプローチを使用して、リクエストの入力パラメータをどのように検証しますか? – Jim

+0

'HttpURLConnection'ではなく' URL'と 'URLConnection'を直接使うべきです。 'HttpURLConnection'には何も役に立ちません。これは、トランスポート層を抽象化するためのURLの目的です。 –

答えて

0

.withParameterTypes(x).withArguments(x)の違いはわかりませんが、コードを動作させるには次のように設定する必要があると思います。これが役に立たない場合は試してみてください。

PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection); 
PowerMockito.whenNew(URL.class).withArguments(Mockito.anyString()).thenReturn(mockedURL); 
+0

私はこれらの行を試しましたが、私は同じ結果を見ています。疑似オブジェクトを使用する代わりに、実際のURLおよびHttpURLConnectionクラスが作成され使用されます。問題は、URLクラスがfinalとして宣言されているという事実にありますか?私が読んだことから、PowerMockitoはこれを処理できるはずです。 – Jim

0

問題は、実際の呼び出しの引数が、あなたのモックで予想されるものと一致しないことです。

PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL)mockedURLを返します。コールはnew URL("MyURLString")です。あなたはそれを変更すると

PowerMockito.whenNew(URL.class).withParameterTypes(String.class) 
    .withArguments(org.mockito.Matchers.any(String.class)).thenReturn(mockedURL); 

それはにコンストラクタURL(String)(でもnull)に渡された任意の文字列をキャッチし、あなたのモックを返します。


あなたは

を試してみました "whenNew(URL.class).withAnyArguments()" と に "thenReturnを" 変更 "thenAnswerは、" 私はそれをトリガーするために得ることができます。唯一の問題は私が決して 自分のコードのURL呼び出しを取得しないことです。私が見ているのは、 パラメータのURLをすべて持つnull.classの3引数コンストラクタの呼び出しです。

PowerMockは、それが(3つの引数付き)最初の呼び出し、その答えを模擬すべてコンストラクタ(ライン122でorg.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing.InvokeStubMethod)を模擬しようとします。しかし、その後の呼び出しでは、の引数をとして偽装するように指示したので、すでに嘲笑された呼び出しを返します。そのため、Answernull, null, nullという電話が1回しか表示されません。

+0

私はあなたの提案のバリエーションを含め、この作業をしようとする過程で多くのことを試しました。あなたが言及しているように、whenNew行を変更して再テストしましたが、同じ結果が得られます。他の考え? – Jim

0

PowerMockito.whenNewを使用するとき、それはよくある間違いです。

MyClass自体ではなく、テスト用MyClassの新しいインスタンスを作成するクラスを準備する必要があります。例えば。新しいMyClassのをやっクラスは()Xと呼ばれているならば、あなたはwhenNewだからPowermock wiki

から

を動作させるには@PrepareForTest(X.class)を行う必要があるだろう、あなたは少しの変更を必要としますテストとは@PrepareForTestURLの新しいインスタンスを作成したクラスを追加したいと:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ URL.class, MockedHttpConnection.class , ConnectionUser.class}) 
public class URLTest { 
public class URLTest { 

    private ConnectionUser connectionUser; 

    @Before 
    public void setUp() throws Exception { 

     connectionUser = new ConnectionUser(); 
    } 

    @Test 
    public void testName() throws Exception { 

     URL mockedURL = PowerMockito.mock(URL.class); 
     MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class); 

     PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL); 
     PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection); 

     connectionUser.open(); 

     assertEquals(mockedConnection, connectionUser.getConnection()); 


    } 
} 

場所:

public class ConnectionUser { 

    private String wlInvokeUrlString = "MyURLString"; 
    private HttpURLConnection connection; 

    public void open() throws IOException { 
     URL wlInvokeUrl = new URL(wlInvokeUrlString); 
     connection = (HttpURLConnection) wlInvokeUrl.openConnection(); 
    } 

    public HttpURLConnection getConnection() { 
     return connection; 
    } 
} 
+0

あなたの答えは仕事に最も近いものです。これらの変更を行った後、模擬URLコンストラクタが呼び出されています。ただし、常にnullオブジェクトが返されます。これにより、 'URL wlInvokeUrl = new URL(wlInvokeUrlString);'という行は常にwlInvokeUrlをnullに割り当てます。私は自分のコードをリファクタリングすることで元の問題を解決しましたが、他の提案がある場合に備えてPowerMockitoがこれを動作させることに専念しています。 – Jim

+0

PowerMock、Mockito、Javaのどのバージョンをお使いですか?私は最新のリリースとMockito 1.10.19でテストし、 'mockedUrl'を' null'に置き換えた場合にのみ問題を再現できます。 。このように: 'PowerMockito.whenNew(URL.class).withArguments( "MyURLString")thenReturn(NULL);'以外の場合はすべての試験の私のバージョンが渡されます。ところで、私はJava 8を使ってテストを実行します。 –

+0

あなたの環境で私のバージョンを稼働させてもらえますか? –

関連する問題