Back to Repositories

Testing EventBus Android Thread Ordering in greenrobot/EventBus

This test suite evaluates event ordering behavior in EventBus for Android applications, specifically focusing on how events are handled between background and main threads. It validates the differences between ordered and unordered event delivery mechanisms in the EventBus framework, ensuring proper event sequencing across different thread modes.

Test Coverage Overview

The test suite provides comprehensive coverage of EventBus thread handling and event ordering mechanisms.

  • Tests both ordered and unordered event delivery scenarios
  • Verifies event sequencing between main thread and background thread posts
  • Validates ThreadMode.MAIN and ThreadMode.MAIN_ORDERED behaviors
  • Covers event posting order preservation

Implementation Analysis

The testing approach utilizes JUnit with Android-specific components to validate event bus behavior.

Key implementation patterns include:
  • Handler and Looper usage for main thread operations
  • Custom background poster implementation for controlled testing
  • Event tracking mechanisms for verification
  • Thread-specific event posting scenarios

Technical Details

Testing infrastructure includes:

  • JUnit test framework
  • Android Handler and Looper for thread management
  • Custom TestBackgroundPoster implementation
  • Event subscription annotations (@Subscribe)
  • ThreadMode configurations for event handling

Best Practices Demonstrated

The test suite exemplifies several testing best practices for Android event handling.

  • Proper test setup and teardown management
  • Clear separation of ordered vs unordered test cases
  • Explicit thread handling and synchronization
  • Controlled timing with waitForEventCount
  • Clean test organization with focused test methods

greenrobot/eventbus

EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java

            
package org.greenrobot.eventbus;

import android.os.Handler;
import android.os.Looper;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;


import static org.junit.Assert.assertEquals;

public class EventBusAndroidOrderTest extends AbstractAndroidEventBusTest {

    private TestBackgroundPoster backgroundPoster;
    private Handler handler;

    @Before
    public void setUp() throws Exception {
        handler = new Handler(Looper.getMainLooper());
        backgroundPoster = new TestBackgroundPoster(eventBus);
        backgroundPoster.start();
    }

    @After
    public void tearDown() throws Exception {
        backgroundPoster.shutdown();
        backgroundPoster.join();
    }

    @Test
    public void backgroundAndMainUnordered() {
        eventBus.register(this);

        handler.post(new Runnable() {
            @Override
            public void run() {
                // post from non-main thread
                backgroundPoster.post("non-main");
                // post from main thread
                eventBus.post("main");
            }
        });

        waitForEventCount(2, 1000);

        // observe that event from *main* thread is posted FIRST
        // NOT in posting order
        assertEquals("non-main", lastEvent);
    }

    @Test
    public void backgroundAndMainOrdered() {
        eventBus.register(this);

        handler.post(new Runnable() {
            @Override
            public void run() {
                // post from non-main thread
                backgroundPoster.post(new OrderedEvent("non-main"));
                // post from main thread
                eventBus.post(new OrderedEvent("main"));
            }
        });

        waitForEventCount(2, 1000);

        // observe that event from *main* thread is posted LAST
        // IN posting order
        assertEquals("main", ((OrderedEvent) lastEvent).thread);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(String event) {
        trackEvent(event);
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void onEvent(OrderedEvent event) {
        trackEvent(event);
    }

    static class OrderedEvent {
        String thread;

        OrderedEvent(String thread) {
            this.thread = thread;
        }
    }

}