これは、子のメソッドがスーパークラスのメソッドと異なる場合にのみ PowerMock で可能だと思います (つまり、子がそのメソッドをオーバーライドする場合、親メソッドをモックすることはできません)。もう少し詳細については、関連するバグ レポートを参照してください。
PowerMock については、Suppressing Unwanted Behavior ページをチェックして、ニーズに十分かどうかを確認してください。
いろいろ調べた結果、これらのトリッキーなケースにはJMockitを使用することになりました。JMockit に移る前に、抑制を使用して例外がスローされたすべての場所をスタブ化しようとしました。最終的に、いくつかのメソッドを単に抑制するだけでなく、オーバーライドする必要があったため、最終的には破棄しました。
Android ケースの使用例:
まず、@MockClass
アノテーションを使用してスーパークラスをモックアウトします。
@MockClass(realClass = Activity.class, instantiation = PerMockedInstance)
public class FakeActivity {
public Bundle mSavedInstanceState;
@Mock
public void $init() {}
@Mock
public void onCreate(Bundle savedInstanceState) {
mSavedInstanceState = savedInstanceState;
}
}
アクティブ化されると、このクラスは のデフォルト コンストラクターを にActivity
置き換え$init()
、onCreate
メソッドを上記のものに置き換えます。Android では、テスト対象のユニットは Activity から派生します (私のサンプル コードでは、それは ですHelloTestActivity
)。テストクラスは次のようになります。
public class HelloTestActivityTest3 extends AndroidTest {
@Tested
HelloTestActivity activity;
FakeActivity fakeActivity = new FakeActivity();
@Before
public void setupMocks()
{
Mockit.setUpMock(fakeActivity);
}
@Test
public void onCreate_bundle(@Mocked Bundle savedInstanceState)
{
// Try to access out-of-band information from the fake
activity.onCreate(savedInstanceState);
assertSame(savedInstanceState, fakeActivity.mSavedInstanceState);
}
}
この呼び出しMockit.setupMock(fakeActivity)
により、スーパー クラスが偽物のインスタンスに置き換えられます。この使用法により、偽のクラスの内部状態にもアクセスできます。カスタム機能でメソッドをオーバーライドする必要がない場合は、Mockit
クラスから利用可能な他のメソッドを使用できます。
以下のコメントで rogerio が指摘したように、Activity
クラスのモックは最低限必要です。次のコードはこれを示しています。
public class HelloTestActivityTest4 {
@Tested
HelloTestActivity activity;
@Mocked
Activity base;
@Test
public void testOnCreate() throws Exception {
// Just make sure "Stub!" exception is not thrown.
activity.onCreate(null);
}
}
この宣言@Mocked Activity base;
により、Activity
クラスとそのスーパークラスのすべてのメソッド (静的初期化子を除く) が で定義されたテストでモック化されHelloActivityTest4
ます。