Friday, September 14, 2012

Haha Service!

What am I doing? I am mocking at a Service! :) Well, what I really wanted to do was write unit test case for one of my java services and mock its dependent services. So the title should be more along the lines of "Haha Dependent Services!". I will try to show mocking in action after looking at the sample tutorial from dzone.

Say I have the following classes:
public interface SpecialService {
    List<SpecialClass1> getSpecialObjects(String criterion);
}

public class SpecialServiceImpl implements SpecialService {
    private SpecialDAO specialDAO;
    public List<SpecialClass1> getSpecialObjects(String criterion) {
        return specialDAO.getSpecialObjects(criterion);
    }
    public void setSpecialDAO(SpecialDAO specialDAO) {
        this.specialDAO = specialDAO;
    }
}

The unit test case for this class using Mockito would look like:
@RunWith(MockitoJUnitRunner.class)
public class SpecialServiceUnitTest {
    @Mock
    private SpecialDAO mockSpecialDAO;
    @InjectMocks
    private SpecialService specialService = new SpecialServiceImpl();
    @Test
    public void testGetSpecialObjects() {
        List<SpecialClass1> testSpecialObjects = getTestSpecialObjects();
        Mockito.when(mockSpecialDAO.getSpecialObjects(Mockito.anyString()))
                .thenReturn(testSpecialObjects);

        String criterion = "mySpecialCriteria";
        List<SpecialClass1> obtainedSpecialObjects = specialService
                .getSpecialObjects(criterion);
        assertNotNull(obtainedSpecialObjects);
        assertEquals(obtainedSpecialObjects.size(), testSpecialObjects.size());
    }

    private List<SpecialClass1> getTestSpecialObjects() {
        List<SpecialClass1> specialObjects = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            specialObjects.add(new SpecialClass1());
        }
        return specialObjects;
    }
}

Let's disect the class:

  • MockitoJUnitRunner is the runner class (akin to our favorite SpringJUnit4ClassRunner) which will take care of processing the annotations of @Mock and @InjectMocks

  • @Mock identifes the dependent entity to be mocked. Here it is the SpecialDAO that needs to be mocked.

  • @InjectMocks is used to indicate the class that is being tested. This class is introspected for dependent entities that are being made available as mocks via the @Mock annotation. Note the instantiation of the implementation. Mockito uses this instance and tries using constructor injection, setter injection and property injection (in that order) to inject the mocks.

  • @Test is used to indicate to JUnit that this is a test method

  • In getTestSpecialObjects(), we prepare a list of special objects that we are going to have the mocked DAO return.

  • Mockito.when is invoked with the call to the mocked DAO. The DAO call expects a String, but since we want to return the same result for all inputs, we pass Mockito.anyString(). We then chain it up to the thenReturn clause which binds it to the list of special objects created earlier.

  • Now proceed with the calls as in the vanilla scenario and use regular asserts to ensure correctness. You may use Mockito.verifyto assert a bunch of other expectations.
I had packaged it as a maven project for others to play around after this - unfortunately couldn't upload it here as one can only upload images or other media, it seems. And I am too lazy to setup a github for it right now :)

Hope this helps!

References:

No comments:

Post a Comment