I have the following stripped down classes (let's pretend the Service interface just has the single overriden method for simplicity). No matter what I try, I always get a NullPointerException when the ServiceImpl
calls getSqlSession()
. How can I override this call to avoid the exception? I have tried creating a spy ServiceImpl and calling when
on the method getSqlSession()
, but I still get the exception. I do not want to put the logic within ServiceImpl.getData()
that changes the List<Object>
into a Map<String,Object>
into the test class since if this implementation ever changes, the test code needs to be changed also. Any suggestions?
public class ServiceImpl extends BaseService implements Service {
@Autowired
private ServiceDAO serviceDao;
@Override
public Map<String, Object> getData() {
Map<String,Object> map = new HashMap<String,Object>();
List<Object> resultSet = service.getData(getSqlSession());
map.put("Test", resultSet.get(0));
map.put("Test2", resultSet.get(1));
return map;
}
public void setServiceDao(final ServiceDAO serviceDao) {
this.serviceDao = serviceDao;
}
}
The BaseService:
public class BaseService {
@Autowired
private ApplicationContext context;
public SqlSession getSqlSession() {
return (SqlSession)context.getBean("SQL_SESSION");
}
public void setContext(ApplicationContext context) {
this.context=context;
}
}
The DAO
public class ServiceDAO {
public List<Object> getData(SqlSession sqlSession) {
return sqlSession.selectList("proc_name");
}
}
And the Test Class:
public class ServiceImplTest {
private Service service;
@Mock
private ServiceDAO serviceDao;
@Before
public void before() {
MockitoAnnotations.initMocks(this);
service = new ServiceImpl();
service.serviceDao = this.serviceDao;
}
@Test
public void testGetData() {
Mockito.when(service.getData()).then(new Answer<List<Object>>() {
@Override
public List<Object> answer(InvocationOnMock invocation) throws Throwable {
return serviceDAO.getData(new DefaultSqlSession(null,null));
}
});
service.getData();
}
}
Was finally able to get this working with below test class. Had to change the Service
declaration from the Interface to the actual Impl class. Not sure if there is any way around this as all other attempts have not worked.
public class ServiceImplTest {
@Mock
private ServiceDAO serviceDAO;
@Spy
private ServiceImpl service;
@Before
public void before() {
MockitoAnnotations.initMocks(this);
//service = new ServiceImpl();
service.setServiceDAO(this.serviceDAO);
}
@Test
public void testGetData() {
Mockito.doAnswer(new Answer<SqlSession>(){
@Override
public SqlSession answer(InvocationOnMock invocation) throws Throwable {
return new DefaultSqlSession(null,null);
}
}).when(service).getSqlSession();
Mockito.when(service.getData()).then(new Answer<List<Object>>() {
@Override
public List<Object> answer(InvocationOnMock invocation) throws Throwable {
return serviceDAO.getData(new DefaultSqlSession(null,null));
}
});
service.getData();
}
}