This post is a short introduction to mocking using two of my favorite mocking frameworks, namely PowerMock and Mockito.
Mockito is a mocking framework that allows you to easily create mocks and, if you want to, verify that the correct behavior was carried out.
Let's start with a small example that demonstrates why mocking is necessary, if we want to create "real" unit-tests. Imagine that we are going to implement a unit-test for an method with the following signature String getPersonInfo() which resides inside a PersonService class and the PersonService relies on a PersonDAO, a PersonProperty and a PersonWebservice class. In order to implement a "real" unit test, for the aforementioned method, it's nessesary to make sure that the test can run in isolation, which means that mocking out PersonService dependencies should be done - in this case the DAO, PersonProperty and Webservice classes.
1. create a test - in this example JUnit is being used
public class PersonTest {
@Test
public void testPersonService_getDetailsForKnownPerson_returnsDetailsForPerson(){
}
}
2. Create mocks for PersonServices dependencies.
The way to create mocks with Mockito is to call Mockito.mock() (you can use import static org.mockito.Mockito.*;), which takes as argument the class that is to be mocked. For instance if we want to mock the PersonDAO, we would write something like this: PersonDAO mockPersonDAO = Mockito.mock(PersonDAO.class); This returns a nice mock (all mocks in Mockito are nice) that will return default values for all methods. As mentioned earlier, PersonService relies on a PersonProperty class that for some reason is implemented using static methods, which PersonService uses - Just to make it absolutely clear, don't do this at home kids. This is were PowerMock comes into the play, because it allows us to mock static methods. The test, that are using PowerMock, should use PowerMockRunner with the @RunWirth annotation. Furthermore PowerMock requires you to specify the class, which contains the static methods, to be specified using @PrepareForTest. So our test now looks like this:@RunWith(PowerMockRunner.class)
@PrepareForTest({PersonProperty.class})
public class PersonTest {
@Test
public void testPersonService_getDetailsForKnownPerson_returnsDetailsForPerson(){
}
}
After setting up powermock, we are going to mock PersonService's dependencies as follows: public class PersonTest
...
private PersonDAO mockPersonDAO;
private PersonWebservice mockPersonWebservice;
private PersonServiceImpl sut;
@Before
public void setUp(){
initializeMocks();
sut = new PersonServiceImpl();
sut.setDao(mockPersonDAO);
sut.setWebservice(mockPersonWebservice);
}
private void initializeMocks(){
mockPersonDAO = mock(PersonDAO.class);
mockPersonWebservice = mock(PersonWebservice.class);
PowerMockito.mockStatic(PersonProperty.class);
}
...
}
As you can see from the code it's pretty straightforward to set up the mocks - just use mock() for Mockito and mockStatic() for Powermock.
3. Set up mock behavior/expectations and verify
First the code:@RunWith(PowerMockRunner.class)
@PrepareForTest({PersonProperty.class})
public class PersonTest {
...
@Test
public void testPersonService_getDetailsForKnownPerson_returnsDetailsForPerson(){
Integer personId = 1;
Person person = new Person();
String wsCallResult = "Person info : blah";
String propertyName = "address";
String address = "44 Taumata road Auckland";
//Set up mock behavior
when(mockPersonDAO.getMeAPerson(personId)).thenReturn(person);
when(mockPersonWebservice.getMeSomePersonInfo(person)).thenReturn(wsCallResult);
when(PersonProperty.getProp(propertyName)).thenReturn(address);
Assert.assertEquals(wsCallResult + address, sut.getPersonInformation(personId));
//Verify mock behavior - optional
verify(mockPersonDAO, atLeastOnce()).getMeAPerson(personId);
verify(mockPersonWebservice, atLeastOnce()).getMeSomePersonInfo(person);
}
...
}
Mockito comes with a DSL (Domain Specific Language) that allows you to quickly set up mock behavior, like: when(someObject.someMethod()).thenReturn(someReturnValue); for more examples go to Mockito WIKI. After setting up the behavior, you might want to verify (optional), that the correct behavior was carried out. This is done by calling verify() after the SUT is executed.
Powermock comes with implementations for EasyMock or Mockito (for now), which uses the underlying concepts of the particular framework - this allows you to use your existing knowledge of a particular framework.


No comments:
Post a Comment