简体   繁体   English

单元测试-为什么我的单元测试在使用finish(),处理程序和线程的代码上失败?

[英]unit test - why does my unit test fail on this code that uses finish(), handler, and thread?

Here is the activity I am testing. 这是我正在测试的活动。 I wish I could write it the other way since I heard using thread.sleep is dangerous. 我希望我可以用其他方式写它,因为我听说使用thread.sleep是危险的。 But I'm not allowed to do that. 但是我不允许这样做。

Here is what this code does: when onCreate is called, MainActivity pauses for a couple of seconds, then it fires Activity2 这是这段代码的作用:调用onCreate时, MainActivity暂停几秒钟,然后触发Activity2

  public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                goToAct2();
            }
        };

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    handler.sendEmptyMessage(0);

                } catch (InterruptedException e) {}
            }
        }).start();

    }
    private void goToAct2(){

    Intent i = new Intent (this,Activity2.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(i);
    finish();
    }
}

I want to test if MainActivity calls the correct Activity (which is Activity2). 我想测试MainActivity是否调用正确的Activity(即Activity2)。 Here is the unit test code: 这是单元测试代码:

public class MainActivityTest extends
        ActivityInstrumentationTestCase2<MainActivity>
{

    MainActivity activity;

    public MainActivityTest()
    {
        super(MainActivity.class);
    }

    protected void setUp() throws Exception
    {
        super.setUp();
        activity=getActivity();
    }

    @UiThreadTest
    public void testOne()
    {
        ActivityMonitor Act2Monitor = getInstrumentation().addMonitor(Activity2.class.getName(), null, false);  
        getInstrumentation().callActivityOnCreate(activity, null);;
        assertEquals(1, Act2Monitor.getHits());
    }
}

I notice that: 我注意到:

  1. If I discard the handler-thread part: 如果我放弃处理程序线程部分:

    calling goToAct2() directly in onCreate(), the test still fails. 直接在onCreate()中调用goToAct2() ,测试仍然失败。 But if I delete finish() in that method, the test passes. 但是,如果我在该方法中删除finish() ,则测试通过。

  2. If I keep the handler-thread part: 如果保留处理程序线程部分:

    No matter what I do, the test keeps on failing even the actual activity works as it supposed to. 无论我做什么,即使实际活动按预期运行,测试仍会失败。

What is going on under the hood? 到底发生了什么事? And, how do I properly write a test that can confirm the creation of Activity2? 而且,如何正确编写可以确认Activity2创建的测试?

In your application activity code you should have something like this: 在应用程序活动代码中,您应该具有以下内容:

Intent i = new Intent(this, SecondActivity.class);
startActivityForResult(i, 1);

In activity2 set the data which you want to return back to FirstActivity. 在activity2中,设置要返回到FirstActivity的数据。

Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(Activity.RESULT_OK,returnIntent);
finish();

Then in the main activity, override the onActivityResult method to process the result. 然后在主活动中,重写onActivityResult方法以处理结果。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == 1) {
        if(resultCode == Activity.RESULT_OK){
            String result=data.getStringExtra("result");
        }
        else {
            //Write your code if there's no result
        }
    }
}

Finally, in your test case use the class ActivityUnitTestCase and call either the isFinishCalled() or getFinishedActivityRequest() to inspect the parameters that they were called with. 最后,在测试用例中,使用类ActivityUnitTestCase并调用isFinishCalled()getFinishedActivityRequest()来检查调用它们的参数。

The documentation for this is at: 有关此文档,请访问:

https://developer.android.com/reference/android/test/ActivityUnitTestCase.html#isFinishCalled() https://developer.android.com/reference/android/test/ActivityUnitTestCase.html#isFinishCalled()

I cannot create a comment so I have to post this as an asnwer sorry. 我无法创建评论,因此我不得不发表评论以表示歉意。

From what I read you need to call the getActivity() after the finish() method has been called. 从我的阅读中,您需要在调用finish()方法之后调用getActivity()。

Meanning the instance you have stored in activity is not the new activity but the one that got destroy. 意味着您存储在活动中的实例不是新活动,而是被销毁的那个活动。 I would sugest trying to change getInstrumentation().callActivityOnCreate(activity, null); 我会尝试更改getInstrumentation()。callActivityOnCreate(activity,null); to getInstrumentation().callActivityOnCreate(getActivity(), null); 到getInstrumentation()。callActivityOnCreate(getActivity(),null); This should return the current activity and not the one that has been destroyed. 这应该返回当前活动,而不是已被破坏的活动。

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM