[英]How can I unit test an Intent launched/sent from an Activity?
How can I create Android JUnit test case which tests the content of an Intent generated within an Activity? 如何创建Android JUnit测试用例来测试Activity中生成的Intent的内容?
I've got an Activity that contains a EditText window, and when the user has finished entering the required data, the Activity launches an Intent to an IntentService which records the data and continues with the application process. 我有一个包含EditText窗口的Activity,当用户输入完所需的数据后,Activity会向IntentService启动一个Intent,它会记录数据并继续执行应用程序。 Here is the class I want to test, the OnEditorActionListener/PasscodeEditorListener is created as a separate class:
这是我想要测试的类,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;
}
}
How can I intercept the two possible outbound Intents generated by the activity and verify their contents? 如何拦截活动生成的两个可能的出站Intent并验证其内容?
Thanks 谢谢
I figured how to use ContextWrapper with the help of another website. 我想到了如何在另一个网站的帮助下使用ContextWrapper。
Use ContextWrapper and override all of the intent functions. 使用ContextWrapper并覆盖所有intent函数。 Generalizing for all of my Activity tests, I extended the ActivityUnitTestCase class and implemented the solution as a shim.
对我的所有Activity测试进行推广,我扩展了ActivityUnitTestCase类并将解决方案实现为垫片。 Enjoy:
请享用:
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<T extends Activity> extends ActivityUnitTestCase<T> {
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<T> 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();
}
}
Alternatively, you could re-factor your code in order to do "clean" unit-test (I mean a unit test that has everything mocked out except the class under test). 或者,您可以重新考虑代码以进行“清理”单元测试(我的意思是一个单元测试,除了被测试的类之外,其他一切都被模拟了)。 Actually, I have a situation myself, where I get a
java.lang.RuntimeException: Stub!
实际上,我自己有一个情况,我得到一个
java.lang.RuntimeException: Stub!
because the code I want to unit test creates new Intents containing mocks that I have injected. 因为我想要单元测试的代码创建了包含我注入的模拟的新Intent。
I consider creating my own factory for intents. 我考虑为意图创建自己的工厂。 Then I could inject a mocked out factory to my class-under-test:
然后我可以把一个模拟出来的工厂注入我的测试班:
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.
....
}
}
My situation is not the same as yours, but I believe you could apply a factory-pattern to solve it as well. 我的情况和你的情况不一样,但我相信你也可以运用工厂模式来解决它。 I prefer to write code to support true unit tests, but must admit that your solution is quite clever.
我更喜欢编写代码来支持真正的单元测试,但必须承认你的解决方案非常聪明。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.