如何在android中发布Event Bus发布的单元测试方法?

时间:2016-05-13 05:41:03

标签: android unit-testing mockito

我在我的应用程序中使用Otto的事件总线。在我的一个课程中,我发布了这个活动。

MyEvent myevent = new MyEvent();
uiBus.post(myEvent);

我可以测试post方法。

现在有另一个班级正在接收活动。

//ReceiverClass.java
@Subscribe
public void onEventReceived(MyEvent myevent) {
    callAMethod();
}

如何进行单元测试以调用此方法。我尝试使用以下测试代码

@Mock
Bus uiBus;

@Test
public void testBusReceviedEvent() {
    ReceiverClass instance = new ReceiverClass();
    mockBus.register(instance);
    MyEvent myevent = new MyEvent();
    mockBus.post(myEvent);
    //Test
    verify(instance, times(1)).callAMethod();
}

但是这段代码不起作用。

2 个答案:

答案 0 :(得分:3)

我参加聚会的时间有点晚了,但这里有一个可以解决异步调用的类的例子。我们只是让它做它并将其注册到下面的TestDriver类中,而不是模拟EventBus。

使这项工作成功的是CountDownLatch,它在抽象DataTransferCallback类的帮助下等待latch.countDown()被调用或等待5秒。

只需注册您的测试类,并在@Subscribe方法中,将其传递回创建DataTransferCallback的方法并在那里执行您的断言。

@RunWith(AndroidJUnit4.class)
public class TestDriver {

    private final CountDownLatch latch = new CountDownLatch(1);
    private EventBus eventBus;

    private DataTransferCallback transferCallback;

    public abstract class DataTransferCallback {
        abstract void onSuccess(DataTransfer event);
    }

    @Before
    public void setUp() {
        EventBus.getDefault().register(this);
        eventBus = spy(EventBus.getDefault());
    }


    @SuppressWarnings("unchecked")
    @Test
    public void test200Resposne() throws InterruptedException {
    // Get known good JSON
    final String json = TestJSON.get200Response();
    // Class under test
    final Driver driver = new Driver(InstrumentationRegistry.getTargetContext());
    final JsonParser jsonParser = new JsonParser();
    //boolean to hold our test result
    final boolean[] testPassed = new boolean[]{false};

    transferCallback = new DataTransferCallback() {

        @Override
        public void onSuccess(DataTransfer event) {
            assertNotNull(event);
            verify(eventBus).post(event);
            assertThat(event.getStatus(), is("OK"));
            assertTrue(event.getData() != null);
            testPassed[0] = true;
        }
    };

    //Set our test EventBus object
    driver.setEventBus(eventBus);
    // The actual method under test
    driver.parseData(jsonParser.parse(json));

    // Set a countdown latch to wait for the result (5s)
    latch.await(5000, TimeUnit.MILLISECONDS);
    // will wait here until 5s or the @Subscrube method is hit
    assertTrue(testPassed[0]);
}

//Because we want to examine EventBus Output, register it 
//to this class and pass the event back through our custom abstract class
@Subscribe
public void onReceiveEventBusEvent(DataTransfer event) {
    assertNotNull(transferCallback);
    transferCallback.onSuccess(event);
    //notify latch so that we can proceed
    latch.countDown();
    }
}

答案 1 :(得分:1)

它不起作用,因为instance不是模拟。您必须验证callAMethod的效果或将该方法放在另一个类中,并将此新类的模拟注入您的ReceiverClass类。

例如......

private class ReceiverClass {
    private MyNewClass theNewClassIWasTalkingAbout;

    // Stick in a setter for that ^

    @Subscribe
    public void onEventReceived(MyEvent myevent) {
        theNewClassIWasTalkingAbout.callAMethod();
    }
}

然后你的测试必须稍微改变......

@Mock
private MyNewClass mockNewClass;

@InjectMocks // This will be the "solid" implementation of the thing you are trying to test, it is not a mock...
private ReceiverClass instance;

@Test
public void testBusReceivedEvent() {
    mockBus.register(instance);
    MyEvent myevent = new MyEvent();

    mockBus.post(myevent);

    verify(mockNewClass, times(1)).callAMethod();
}

希望这有帮助。