I am trying to mock an inner method call of my test method
My class looks like this
public class App {
public Student getStudent() {
MyDAO dao = new MyDAO();
return dao.getStudentDetails();//getStudentDetails is a public
//non-static method in the DAO class
}
When I write the junit for the method getStudent(), is there a way in PowerMock to mock the line
dao.getStudentDetails();
or make the App class use a mock dao object during junit execution instead of the actual dao call which connects to the DB?
You can use the whenNew()
method from PowerMock (see https://github.com/powermock/powermock/wiki/Mockito#how-to-mock-construction-of-new-objects)
Full Test Case
import org.junit.*;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest(App.class)
public class AppTest {
@Test
public void testGetStudent() throws Exception {
App app = new App();
MyDAO mockDao = Mockito.mock(MyDAO.class);
Student mockStudent = Mockito.mock(Student.class);
PowerMockito.whenNew(MyDAO.class).withNoArguments().thenReturn(mockDao);
Mockito.when(mockDao.getStudentDetails()).thenReturn(mockStudent);
Mockito.when(mockStudent.getName()).thenReturn("mock");
assertEquals("mock", app.getStudent().getName());
}
}
I manufactured a simple Student class for this test case:
public class Student {
private String name;
public Student() {
name = "real";
}
public String getName() {
return name;
}
}
In order to get much out of the mocking framework, the MyDAO object has to be injected. You can either use something like Spring our Guice, or simply use a factory pattern to supply you with the DAO object. Then, in your unit test, you have a test factory to supply you with mock DAO objects instead of real ones. Then you can write code such as:
Mockito.when(mockDao.getStudentDetails()).thenReturn(someValue);
If you don't have access to Mockito, you can also use PowerMock to do the same purpose. For example you could do the following:
@RunWith(PowerMockRunner.class)
@PrepareForTest(App.class)
public class AppTest {
@Test
public void testGetStudent() throws Exception {
MyDAO mockDao = createMock(MyDAO.class);
expect(mockDao.getStudentDetails()).andReturn(new Student());
replay(mockDao);
PowerMock.expectNew(MyDAO.class).andReturn(mockDao);
PowerMock.replay(MyDAO.class);
// make sure to replay the class you expect to get called
App app = new App();
// do whatever tests you need here
}
}