如何让我的 ActivityUnitTestCases 与 MessageQueue 线程同步并调用我的处理程序?

发布于 2024-08-26 20:35:27 字数 1677 浏览 5 评论 0原文

我正在为 Android 中的 ListActivity 编写单元测试,该测试使用处理程序来更新 ListAdapter。虽然我的 Activity 在 Android 模拟器中运行,但在单元测试中运行相同的代码不会更新我的适配器:对 sendEmptyMessage 的调用不会在我的 Activity 的处理程序中调用 handleMessage。

如何让 ActivityUnitTestCase 与 MessageQueue 线程同步并调用我的处理程序?

活动的代码有点像这样:

public class SampleActivity extends ListActivity implements SampleListener {
    List samples = new ArrayList();

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sample_list);
        listView.setEmptyView(findViewById(R.id.empty));
    }

    private final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // unit test never reaches here
            sharesAdapter = new SampleAdapter(SampleActivity.this, samples);
            setListAdapter(sharesAdapter);
        }
    };

    public void handleSampleUpdate(SampleEvent event) {
        samples.add(event.getSample());
        handler.sendEmptyMessage(0);
    }
}

我的单元测试的代码有点像这样:

public class SampleActivityTest extends ActivityUnitTestCase<SampleActivity> {

    public SampleActivityTest() {
        super(SampleActivity.class);
    }

    @MediumTest
    public void test() throws Exception {
        final SampleActivity activity = startActivity(new Intent(Intent.ACTION_MAIN), null, null);
        final ListView listView = (ListView) activity.findViewById(android.R.id.list);
        activity.handleSampleUpdate(new SampleEvent(this));
        // unit test assert fails on this line:
        assertTrue(listView.getCount() == 1);
    }

}

I'm writing unit tests for a ListActivity in Android that uses a handler to update a ListAdapter. While my activity works in the Android emulator, running the same code in a unit test doesn't update my adapter: calls to sendEmptyMessage do not call handleMessage in my activity's Handler.

How do I get my ActivityUnitTestCase to sync with the MessageQueue thread and call my Handler?

The code for the Activity is somewhat like this:

public class SampleActivity extends ListActivity implements SampleListener {
    List samples = new ArrayList();

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sample_list);
        listView.setEmptyView(findViewById(R.id.empty));
    }

    private final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // unit test never reaches here
            sharesAdapter = new SampleAdapter(SampleActivity.this, samples);
            setListAdapter(sharesAdapter);
        }
    };

    public void handleSampleUpdate(SampleEvent event) {
        samples.add(event.getSample());
        handler.sendEmptyMessage(0);
    }
}

The code for my unit test is somewhat like this:

public class SampleActivityTest extends ActivityUnitTestCase<SampleActivity> {

    public SampleActivityTest() {
        super(SampleActivity.class);
    }

    @MediumTest
    public void test() throws Exception {
        final SampleActivity activity = startActivity(new Intent(Intent.ACTION_MAIN), null, null);
        final ListView listView = (ListView) activity.findViewById(android.R.id.list);
        activity.handleSampleUpdate(new SampleEvent(this));
        // unit test assert fails on this line:
        assertTrue(listView.getCount() == 1);
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

南城追梦 2024-09-02 20:35:27

我怀疑但不确定这是因为使用了检测线程和 UIThread 不同步。所以你的处理程序绑定到创建它的线程。您的处理程序是在构造时创建的,因此它是调用构造函数的任何线程。我面前没有源代码,但我的猜测是,在大多数情况下,当应用程序运行时,我打赌它是 UIThead(主要)在您的活动上构造并调用 onCreate() 。但是,当单元测试运行时,它被绑定到可能构建您的活动的 Instrumentation Thread,然后在 UIThread 上调用 onCreate。现在,您在检测线程中说,发送一条消息,并且您的线程没有与之关联的循环程序来对其执行任何操作。所以它只是坐在队列中。尝试将处理程序创建移至 onCreate()。这应该将您的处理程序绑定到主循环程序,然后您的异步事件将从另一个线程(检测线程)触发,并且 UIThread 将很乐意从队列中获取它们。

虽然我还没有测试过,但乍一看这似乎是个问题。

I suspect but I am not certain that this is because of the use of the instrumentation thread and UIThread not syncing up. So your handler is bound to the thread that creates it. Your handler is created at construction time so it's whatever thread calls the constructor. I don't have the source in front of me, but my guess is that in most cases when the app is running, I am betting it's the UIThead (main) both constructs and calls onCreate() on your activity. But when the unit test is running it is being bound to the Instrumentation Thread which probably constructs your activity and then onCreate is called on the UIThread. Now you are saying in the instrumentation thread, send a message and your thread has no looper associated with it to do anything with it. So it just sits in the queue. Try moving your handler creation to the onCreate(). This should bind your Handler to the main looper and then your async events will be fired from another thread (the instrumentation thread) and the UIThread will gladly reap them from the queue.

While I haven't tested it, this seems like the issue at first glance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文