これが私のユニットからのBroadcastReceiverです。これをユニットテストで探しています。ユーザーが電話をかけると、電話番号を取得し、電話番号を渡して新しいアクティビティを開始するインテントを設定します。
public class OutgoingCallReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context xiContext, Intent xiIntent)
{
if (xiIntent.getAction().equalsIgnoreCase(Intent.ACTION_NEW_OUTGOING_CALL))
{
String phoneNum = xiIntent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Intent intent = new Intent(xiContext, MyActivity.class);
intent.putExtra("phoneNum", phoneNum);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
xiContext.startActivity(intent);
setResultData(null);
}
}
}
これまでのところ、私の単体テストは次のようになります。
public class OutgoingCallReceiverTest extends AndroidTestCase
{
private OutgoingCallReceiver mReceiver;
@Override
protected void setUp() throws Exception
{
super.setUp();
mReceiver = new OutgoingCallReceiver();
}
public void testStartActivity()
{
Intent intent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
intent.putExtra(Intent.EXTRA_PHONE_NUMBER, "01234567890");
mReceiver.onReceive(getContext(), intent);
}
}
これはコード全体を実行しますが、インテントが送信されたことをテストで確認し、その電話番号を確認できるようにしたいと思います。どうすればよいですか?
また、(setResultData(null)行のため)通話がキャンセルされることをテストできますか?
マット、
コンテキストをモックアップして、具体的なクラスではなく、インターフェイスを受け入れるようにメソッドを交換する必要があるようです:public void onReceive(IContext c, IIntent i)
、テストのみを目的としています。しかし、ContextクラスとIntentクラスはあなたのものではありません...それらはAndroidのものです...したがって、それらに「ただ」インターフェースを実装させることはできません。そのため、それらを「ラップ」する必要があります。あなたのインターフェースを公開する。とてもヤバイ!!!
だから私は誰かがこれまでにこれまで経験したことがあるかどうか疑問に思い始め、私たちのためにハードヤードをやりました...そしてtada: http://developer.Android.com/reference/Android/test/mock/package -summary.html
乾杯。キース。
corlettkが私をAndroidのMockContextオブジェクトに向けました。そのサブクラスであるTestContextを作成しました。次のようになります。
public class TestContext extends MockContext
{
private List<Intent> mReceivedIntents = new ArrayList<Intent>();
@Override
public String getPackageName()
{
return "com.mypackage.test";
}
@Override
public void startActivity(Intent xiIntent)
{
mReceivedIntents.add(xiIntent);
}
public List<Intent> getReceivedIntents()
{
return mReceivedIntents;
}
}
そして私のテストケースは次のようになります:
public class OutgoingCallReceiverTest extends AndroidTestCase
{
private OutgoingCallReceiver mReceiver;
private TestContext mContext;
@Override
protected void setUp() throws Exception
{
super.setUp();
mReceiver = new OutgoingCallReceiver();
mContext = new TestContext();
}
public void testStartActivity()
{
Intent intent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
intent.putExtra(Intent.EXTRA_PHONE_NUMBER, "01234567890");
mReceiver.onReceive(mContext, intent);
assertEquals(1, mContext.getReceivedIntents().size());
assertNull(mReceiver.getResultData());
Intent receivedIntent = mContext.getReceivedIntents().get(0);
assertNull(receivedIntent.getAction());
assertEquals("01234567890", receivedIntent.getStringExtra("phoneNum"));
assertTrue((receivedIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0);
}
}
この質問が尋ねられて以来、モックフレームワークはかなり進化しました。 mockitoを使用すると、インターフェースだけでなくクラスもモックできます。したがって、コンテキストをモックしてArgumentCaptureを使用することにより、この問題を解決することをお勧めします。
import static org.mockito.Mockito.*;
public class OutgoingCallReceiverTest extends AndroidTestCase {
private OutgoingCallReceiver mReceiver;
private Context mContext;
@Override
protected void setUp() throws Exception {
super.setUp();
//To make mockito work
System.setProperty("dexmaker.dexcache",
mContext.getCacheDir().toString());
mReceiver = new OutgoingCallReceiver();
mContext = mock(Context.class);
}
public void testStartActivity() {
Intent intent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
intent.putExtra(Intent.EXTRA_PHONE_NUMBER, "01234567890");
mReceiver.onReceive(mContext, intent);
assertNull(mReceiver.getResultData());
ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);
verify(mContext, times(1)).startActivity(argument.capture());
Intent receivedIntent = argument.getValue();
assertNull(receivedIntent.getAction());
assertEquals("01234567890", receivedIntent.getStringExtra("phoneNum"));
assertTrue((receivedIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0);
}
}