unit testing广播接收机?

这里是我的项目的BroadcastReceiver,我正在寻找unit testing。 当用户拨打电话时,它抓住电话号码,并build立一个意图开始一个新的活动,传递电话号码。

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); } } } 

到目前为止,我的unit testing看起来像这样:

 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); } } 

这是通过代码运行的,但是我希望我的testing能够检查意图是否已经发出,并检查它的电话号码。 我该怎么做呢?

我还可以testing电话被取消(由于setResultData(空)行)?

马特,

听起来就像你需要模拟上下文…然后交换你的方法接受接口,而不是具体的类: public void onReceive(IContext c, IIntent i) ,只是为了testing的目的。 但是,Context和Intent类不是你的,他们是Android的…所以你不能“只”使它们实现你的接口,所以你必须“包装”它们以便暴露你的界面,这是相当多的代码没有太大的收获。 非常好吃!

所以我开始怀疑是否有人经历过这一切,为我们做了一些艰苦的工作……以及tada: http : //developer.android.com/reference/android/test/mock/package-summary.html

干杯。 基思。

科利特指着我在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; } } 

我的testing案例现在看起来像这样:

 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你现在可以嘲笑不仅接口,而且类。 所以我build议通过嘲笑一个上下文并使用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); } }