如何对从Activity中启动/发送的Intent进行unit testing?

如何创建Android JUnit测试用例来测试Activity中生成的Intent的内容?

我有一个包含EditText窗口的Activity,当用户输入完所需数据后,Activity会向IntentService启动一个Intent,它会记录数据并继续执行应用程序。 这是我想要测试的类,OnEditorActionListener / PasscodeEditorListener是作为一个单独的类创建的:

public class PasscodeActivity extends BaseActivity { EditText m_textEntry = null; PasscodeEditorListener m_passcodeEditorListener = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.passcode_activity); m_passcodeEditorListener = new PasscodeEditorListener(); m_textEntry = (EditText) findViewById(R.id.passcode_activity_edit_text); m_textEntry.setTag(this); m_textEntry.setOnEditorActionListener(m_passcodeEditorListener); } @Override protected void onPause() { super.onPause(); /* * If we're covered for any reason during the passcode entry, * exit the activity AND the application... */ Intent finishApp = new Intent(this, CoreService.class); finishApp.setAction(AppConstants.INTENT_ACTION_ACTIVITY_REQUESTS_SERVICE_STOP); startService(finishApp); finish(); } } class PasscodeEditorListener implements OnEditorActionListener{ @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { PasscodeActivity activity = (PasscodeActivity) v.getTag(); boolean imeSaysGo = ((actionId & EditorInfo.IME_ACTION_DONE)!=0)?true:false; boolean keycodeSaysGo = ((null != event) && (KeyEvent.ACTION_DOWN == event.getAction()) && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER))?true:false; if (imeSaysGo || keycodeSaysGo){ CharSequence seq = v.getText(); Intent guidEntry = new Intent(activity, CoreService.class); guidEntry.setAction(AppConstants.INTENT_ACTION_PASSCODE_INPUT); guidEntry.putExtra(AppConstants.EXTRA_KEY_GUID, seq.toString()); activity.startService(guidEntry); return true; } return false; } } 

如何拦截活动生成的两个可能的出站Intent并validation其内容?

谢谢

我想到如何在另一个网站的帮助下使用ContextWrapper。

使用ContextWrapper并覆盖所有intent函数。 对我的所有Activity测试进行推广,我扩展了ActivityUnitTestCase类并将解决方案实现为垫片。 请享用:

 import android.app.Activity; import android.app.Instrumentation; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.test.ActivityUnitTestCase; public class IntentCatchingActivityUnitTestCase extends ActivityUnitTestCase { protected Activity m_activity; protected Instrumentation m_inst; protected Intent[] m_caughtIntents; protected IntentCatchingContext m_contextWrapper; protected class IntentCatchingContext extends ContextWrapper { public IntentCatchingContext(Context base) { super(base); } @Override public ComponentName startService(Intent service) { m_caughtIntents = new Intent[] { service }; return service.getComponent(); } @Override public void startActivities(Intent[] intents) { m_caughtIntents = intents; super.startActivities(intents); } @Override public void startActivity(Intent intent) { m_caughtIntents = new Intent[] { intent }; super.startActivity(intent); } @Override public boolean stopService(Intent intent) { m_caughtIntents = new Intent[] { intent }; return super.stopService(intent); } } // --// public IntentCatchingActivityUnitTestCase(Class activityClass) { super(activityClass); } protected void setUp() throws Exception { super.setUp(); m_contextWrapper = new IntentCatchingContext(getInstrumentation().getTargetContext()); setActivityContext(m_contextWrapper); startActivity(new Intent(), null, null); m_inst = getInstrumentation(); m_activity = getActivity(); } protected void tearDown() throws Exception { super.tearDown(); } } 

或者,你可以重新考虑你的代码,以便进行“清理”unit testing(我的意思是一个unit testing,除了被测试的类之外,其他一切都被模拟了)。 实际上,我自己有一个情况,我得到一个java.lang.RuntimeException: Stub! 因为我想要unit testing的代码创建了包含我注入的模拟的新Intent。

我考虑为意图创建自己的工厂。 然后我可以把一个模拟出来的工厂注入我的测试class:

 public class MyClassToBeTested { public MyClassToBeTested(IntentFactory intentFactory) { //assign intentFactory to field } .... public void myMethodToTestUsingIntents() { Intent i = intentFactory.create(); i.setAction(AppConstants.INTENT_ACTION_PASSCODE_INPUT); //when doing unit test, inject a mocked version of the //IntentFactory and do the necessary verification afterwards. .... } } 

我的情况和你的情况不一样,但我相信你也可以运用工厂模式来解决它。 我更喜欢编写代码来支持真正的unit testing,但必须承认你的解决方案非常聪明。