Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 464
CodingIntrigue Avatar asked Sep 20 '13 09:09

CodingIntrigue


People also ask

Can you unit test interfaces?

To test an interface with common tests regardless of implementation, you can use an abstract test case, and then create concrete instances of the test case for each implementation of the interface.

Can we test interface in JUnit?

You can use an abstract test case to test an interface with common tests independent of implementation, and then generate concrete instances of the test case for each implementation of the interface.

What should I test in unit tests Android?

Unit tests or small tests only verify a very small portion of the app, such as a method or class. End-to-end tests or big tests verify larger parts of the app at the same time, such as a whole screen or user flow. Medium tests are in between and check the integration between two or more units.


1 Answers

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();
    }

}
like image 161
Debojit Saikia Avatar answered Oct 05 '22 13:10

Debojit Saikia