来自 Super Class 方法调用的 Mockito NullPointerException
Mockito NullPointerException From Super Class Method Call
我有以下精简的 classes(为了简单起见,我们假设服务接口只有一个重写方法)。无论我尝试什么,当 ServiceImpl
调用 getSqlSession()
时,我总是会得到 NullPointerException。如何覆盖此调用以避免异常?我已经尝试创建一个间谍 ServiceImpl 并在方法 getSqlSession()
上调用 when
,但我仍然遇到异常。我不想将 ServiceImpl.getData()
中将 List<Object>
更改为 Map<String,Object>
的逻辑放入测试 class 中,因为如果此实现发生变化,则需要测试代码也变了。有什么建议吗?
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;
}
}
基础服务:
public class BaseService {
@Autowired
private ApplicationContext context;
public SqlSession getSqlSession() {
return (SqlSession)context.getBean("SQL_SESSION");
}
public void setContext(ApplicationContext context) {
this.context=context;
}
}
DAO
public class ServiceDAO {
public List<Object> getData(SqlSession sqlSession) {
return sqlSession.selectList("proc_name");
}
}
和测试 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();
}
}
我相信当您尝试使用服务中的 serviceDao 时会发生错误:
List<Object> resultSet = service.getData(getSqlSession());
如果您在同一个包中,则需要将模拟的 serviceDAO 注入到您的服务中:
@Before
public void before() {
MockitoAnnotations.initMocks(this);
service = new ServiceImpl();
service.service = this.serviceDAO;
}
终于能够在下面的测试中使用它 class。必须将 Service
声明从接口更改为实际的 Impl class。不确定是否有任何解决方法,因为所有其他尝试都没有奏效。
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();
}
}
我有以下精简的 classes(为了简单起见,我们假设服务接口只有一个重写方法)。无论我尝试什么,当 ServiceImpl
调用 getSqlSession()
时,我总是会得到 NullPointerException。如何覆盖此调用以避免异常?我已经尝试创建一个间谍 ServiceImpl 并在方法 getSqlSession()
上调用 when
,但我仍然遇到异常。我不想将 ServiceImpl.getData()
中将 List<Object>
更改为 Map<String,Object>
的逻辑放入测试 class 中,因为如果此实现发生变化,则需要测试代码也变了。有什么建议吗?
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;
}
}
基础服务:
public class BaseService {
@Autowired
private ApplicationContext context;
public SqlSession getSqlSession() {
return (SqlSession)context.getBean("SQL_SESSION");
}
public void setContext(ApplicationContext context) {
this.context=context;
}
}
DAO
public class ServiceDAO {
public List<Object> getData(SqlSession sqlSession) {
return sqlSession.selectList("proc_name");
}
}
和测试 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();
}
}
我相信当您尝试使用服务中的 serviceDao 时会发生错误:
List<Object> resultSet = service.getData(getSqlSession());
如果您在同一个包中,则需要将模拟的 serviceDAO 注入到您的服务中:
@Before
public void before() {
MockitoAnnotations.initMocks(this);
service = new ServiceImpl();
service.service = this.serviceDAO;
}
终于能够在下面的测试中使用它 class。必须将 Service
声明从接口更改为实际的 Impl class。不确定是否有任何解决方法,因为所有其他尝试都没有奏效。
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();
}
}