2016-06-24 11 views
1

私のクラスでonFailureメソッドをテストし、postメソッドがBUSインスタンスで呼び出されたかどうかを検出したいと思います。プライベート静的最終フィールドのメソッドがmockitoで呼び出されたかどうかを検出

私は一日中試してきましたが、私は達成できませんでした。私はジュニアとpowermockとMockitoを使用します。

ApiCallback.java:

package com.example.android.webserver; 

import com.example.android.event.OnApiRequestErrorEvent; 
import com.example.android.event.OnApiResponseErrorEvent; 
import com.example.android.model.ApiRequestError; 
import com.example.android.utils.BusProvider; 
import com.example.android.utils.ErrorUtils; 
import org.greenrobot.eventbus.EventBus; 
import retrofit2.Call; 
import retrofit2.Callback; 
import retrofit2.Response; 

public abstract class ApiCallback<T> implements Callback<T> { 
private final static EventBus BUS; 

static { 
    BUS = BusProvider.getInstance(); 
} 


@Override 
public void onFailure(Call<T> call, Throwable t) { 
    BusProvider.getInstance().post(new OnApiRequestErrorEvent(new ApiRequestError(t.getMessage()))); 
} 


protected void handleResponse(Response<?> response, Object object) { 
    if (response.isSuccessful()) { 
     BusProvider.getInstance().post(object); 
    } else { 
     BUS.post(new OnApiResponseErrorEvent(ErrorUtils.parseError(response), object)); 
    } 
} 
} 

私のテストクラス - ApiCallbackTest.java:一般的に

package com.ashojash.android.webserver; 

import com.ashojash.android.utils.BusProvider; 
import org.greenrobot.eventbus.EventBus; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mock; 
import org.powermock.api.mockito.PowerMockito; 

import static org.mockito.Mockito.verify; 
import static org.powermock.api.mockito.PowerMockito.*; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 
import org.powermock.reflect.Whitebox; 
import retrofit2.Call; 

import static org.mockito.Matchers.any; 
import static org.mockito.Matchers.anyObject; 
import static org.mockito.Mockito.doCallRealMethod; 
import static org.powermock.api.mockito.PowerMockito.mockStatic; 


@RunWith(PowerMockRunner.class) 
@PrepareForTest({BusProvider.class}) 
public class ApiCallbackTest { 

@Mock 
private ApiCallback apiCallback; 
@Mock 
private Call call; 
@Mock 
private Throwable throwable; 

@Before 
public void setUp() { 
} 

@Test 
public void should_call_busProvider_to_post_event() throws Exception { 
//  given 
    doCallRealMethod().when(apiCallback).onFailure(any(Call.class), any(Throwable.class)); 
    doCallRealMethod().when(BusProvider.getInstance()); 
//  when 
    apiCallback.onFailure(call, throwable); 

//  then 
    EventBus bus = BusProvider.getInstace(); 
    verify(bus).post(anyObject()); 
} 
} 
+0

以下の回答はどれですか? –

答えて

2

、任意の "どのようにpowermockを使用する" の質問に対する私の答えは次のとおりです。それを使用しないためにまったく。

私は、パーマネントテストが突然失敗するのに時間を費やしています...私の生産コードでは何の問題も見つけられません。

逆に:「powermockの必要性」は、実際には、あなたが確証できないデザインを考え出したという良い指標です。そして、代わりにのようなあなたのコードを "ハンマー"するためにpowermockを使用するテスト可能な...あなたは良い時間を過ごす固定あなたの悪いデザイン。

そして、PowerMockはバイトコードを操作します。あなたはではありません。はクラスをテストしますが、PowerMockがクラスから作成したものです。スターターとして

、あなたはこれがリファクタリングのためのより良い場合である。このgoogle tech series.

+0

実際、私はあまりあなたに同意しません。静的メソッドをモックしたり、プライベートメソッドを検証する正当な理由があります。 – Mehrdad

+1

プライベートメソッドを検証すると、実装の詳細がわかります。あなたは、他のオブジェクトがあなたのクラスと通信するために使用するパブリックメソッドが、彼らがするべきことをしていることを確認します。あなたがこれを必要としたり、実装するためのプライベートメソッドがクラス内に完全に隠されていなければならないという事実。ホワイトボックス単位のテストを行うときにも表示されません。もちろん、あなたが絶対に**あなたが所有していないコードをテストしなければならない場合**;静的を使用すると、PowerMockが最後の手段です。しかし、あなたは痛みの地に近づいてきています。 – GhostCat

+0

これはOPの質問には答えませんが、PowerMockを使用してコードを "ハンマー"にするという考え方に同意します。 –

2

から少なくとも二つの最初のビデオを視聴することもできます。こうすることで、パッケージに隣接するテストでテストダブルを使用し、必要に応じて新しい隣接クラスでオーバーライドすることができます。

public abstract class ApiCallback<T> implements Callback<T> { 
    private final EventBus bus; 

    public ApiCallback() { 
    this(BusProvider.getInstance()); 
    } 

    /** Package-private for testing. */ 
    ApiCallback(EventBus bus) { 
    this.bus = bus; 
    } 

    @Override 
    public void onFailure(Call<T> call, Throwable t) { 
    bus.post(new OnApiRequestErrorEvent(new ApiRequestError(t.getMessage()))); 
    } 

    protected void handleResponse(Response<?> response, Object object) { 
    if (response.isSuccessful()) { 
     bus.post(object); 
    } else { 
     bus.post(new OnApiResponseErrorEvent(
      ErrorUtils.parseError(response), object)); 
    } 
    } 
} 

代替戦略の詳細なリストについては、How to use Mockito when we cannot pass a mock object to an instance of a classを参照してください。

サイドノート:テスト中のクラスは抽象クラスです。あなたのテストでは、(簡単な実装で)具体的なサブクラスを作成することを検討することをお勧めします。可能であれば抽象メソッドを提供するためにMockitoを使用していますが、APIサーフェイスが変更されたかどうかについての有用なデータポイントはありません。外部コード(サブクラス)が依存するためですその一般契約。

2

モックオブジェクトのメソッド呼び出しのみを検証できます。あなたはBusProvider.getInstance()への呼び出しの結果を疑似しなければなりません。そうすれば、その模擬されたオブジェクトのメソッド呼び出しを確認することができます。

+0

このテストは合格ですか? –

関連する問題