简体   繁体   English

如何对从Activity中启动/发送的Intent进行单元测试?

[英]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.

相关问题 如何对我的Android服务启动特定活动进行单元测试? - How can I unit test that my Android Service launched a particular Activity? 如何通知我的活动警报管理器已启动其挂起的意图? - How can I notify my activity that the alarm manager has launched its pending intent? 如何从通过Intent启动的活动中获取新数据? - How to fetch new data from an activity that was launched through an Intent? 如何从活动中停止在另一个进程中启动的意图服务 - How to stop intent service that is launched in another process from activity 是否可以通知我已发送了活动意图,而没有注册要启动的活动 - Can I be informed that an activity intent was sent without registering an activity for it to start 如何检查一个活动是否收到另一个活动发送的意图? - How to check if an Activity receives an intent sent from another activity? 如何从ActionBar SearchView启动的Search活动中正确返回到父活动。 - How can I return to a parent activity correctly from Search activity which is launched from ActionBar SearchView. 如何对作用于Accelerometer的Android Activity进行单元测试? - How can I unit test an Android Activity that acts on Accelerometer? 活动意图未启动 - Activity Intent not launched 如何检查是否有意图发送的捆绑包? - How can I check if there is a bundle sent with the intent?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM