CodingIntrigue
CodingIntrigue

Reputation: 78545

How to test listener interface is called within Android Unit Tests

I have the following (example) structure within my Android app which I'm trying to write a unit test for:

class EventMonitor {
  private IEventListener mEventListener;

  public void setEventListener(IEventListener listener) {
    mEventListener = listener;
  }

  public void doStuff(Object param) {
    // Some logic here
    mEventListener.doStuff1();
    // Some more logic
    if(param == condition) {
      mEventListener.doStuff2();
    }
  }
}

I want to ensure that when I pass certain values of param, the correct interface methods are called. Can I do this within the standard JUnit framework, or do I need to use an external framework? This is a sample of a unit test I'd like:

public void testEvent1IsFired() {
  EventMonitor em = new EventMonitor();
  em.setEventListener(new IEventListener() {
    @Override
    public void doStuff1() {
      Assert.assertTrue(true);
    }

    @Override
    public void doStuff2() {
      Assert.assertTrue(false);
    }
  });
  em.doStuff("fireDoStuff1");
}

I'm also a beginner in Java, so if this isn't a good pattern for testing purposes I'm willing to change it to something more testable.

Upvotes: 14

Views: 15726

Answers (1)

Debojit Saikia
Debojit Saikia

Reputation: 10632

Here you want to test EventMonitor.doStuff(param) and while executing this method you want to make it sure whether the correct methods on IEventListener were invoked or not.

So, in order to test doStuff(param), you don't need to have a real implementation of IEventListener: what you need is just a mock implementation of IEventListener and you have to verify the exact number of method invocations on IEventListener while testing doStuff. This can be achieved with Mockito or any other mocking framework.

Here is an example with Mockito:

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class EventMonitorTest {

    //This will create a mock of IEventListener
    @Mock
    IEventListener eventListener;

    //This will inject the "eventListener" mock into your "EventMonitor" instance.
    @InjectMocks
    EventMonitor eventMonitor = new EventMonitor();

    @Before
    public void initMocks() {
        //This will initialize the annotated mocks
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test() {
        eventMonitor.doStuff(param);
        //Here you can verify whether the methods "doStuff1" and "doStuff2" 
        //were executed while calling "eventMonitor.doStuff". 
        //With "times()" method, you can even verify how many times 
        //a particular method was invoked.
        verify(eventListener, times(1)).doStuff1();
        verify(eventListener, times(0)).doStuff2();
    }

}

Upvotes: 22

Related Questions