如何使用 Mockito 模拟 Hibernate Query.list()
How to mock Hibernate Query.list() using Mockito
这是我的class需要测试的:
@Repository
@Transactional
public class ProductDAOImpl implements ProductDAO {
private static final Logger logger = Logger.getLogger(ProductDAOImpl.class);
@Autowired
private SessionFactory hibernateSessionFactory;
@Override
public ProductDTO getProduct(String isbn) throws ProductException {
ProductDTO productDTO = new ProductDTO();
Product product = getProductFromDb(isbn);
BeanUtils.copyProperties(product, productDTO);
return productDTO;
}
private Product getProductFromDb(String isbn) throws ProductException{
Session session = this.hibernateSessionFactory.getCurrentSession();
String hql = "FROM com.esp.dao.entity.Product P WHERE P.isbn13 = :isbn13";
Query query = session.createQuery(hql);
query.setParameter("isbn13",isbn);
List<Product> productList = query.list(); // Want to mock this call
if(productList.size() ==1)
return productList.get(0);
else if(productList.size() >1)
// throw new ProductException("Cannot return product. Multiple products found.", HttpServletResponse.SC_NOT_FOUND);
throw new ProductException("Cannot return product. Multiple products found.");
else if(productList.size() == 0){
throw new ProductException("Cannot return product. No products found.");
}
return null;
}
我想模拟 query.list() 方法。到目前为止,这是我尝试过的但出现异常:Type 'SessionFactory' 是一个接口,无法对其进行监视。
@RunWith(MockitoJUnitRunner.class)
public class TestProductDaoImpl {
@Spy
private SessionFactory hibernateSessionFactory;
@InjectMocks
private ProductDAOImpl productDAOImpl;
@Test
public void testGetProduct() throws ProductException {
Session session = this.hibernateSessionFactory.getCurrentSession();
String hql = "";
Query query = session.createQuery(hql);
Query spy = Mockito.spy(query);
List<Product> productList = getProductList();
doReturn(productList).when(spy).list();
productDAOImpl.getProduct("abc");
}
我可以模拟 getProductFromDb()。但在那种情况下,没有必要为此编写测试用例,因为 class 的最大部分正在被模拟。
我认为有两种方法:
第一个:
像这样在 SessionFactory 上创建模拟
@Mock
private SessionFactory hibernateSessionFactory;
@Before
public void beforeTest(){
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetProduct() throws ProductException {
//then mock all you need from hibernateSessionFactory
Session session = Mockito.mock(Session.class);
Query query = Mockito.mock(Query.class);
Mockito.when(hibernateSessionFactory.getCurrentSession()).thenReturn(session);
Mockito.when(session.createQuery("FROM com.esp.dao.entity.Product P WHERE P.isbn13 = :isbn13")).thenReturn(query);
List<Product> productList = new ArrayList<>(1);
Mockito.when(query.list()).thenReturn(productList);
其次:您应该创建 SessionFactory 的实例
private SessionFactory hibernateSessionFactory;
@Before
public void beforeTest(){
hibernateSessionFactory = Mockito.spy(new ConstructorForSessionFactory ());
}
这是我的class需要测试的:
@Repository
@Transactional
public class ProductDAOImpl implements ProductDAO {
private static final Logger logger = Logger.getLogger(ProductDAOImpl.class);
@Autowired
private SessionFactory hibernateSessionFactory;
@Override
public ProductDTO getProduct(String isbn) throws ProductException {
ProductDTO productDTO = new ProductDTO();
Product product = getProductFromDb(isbn);
BeanUtils.copyProperties(product, productDTO);
return productDTO;
}
private Product getProductFromDb(String isbn) throws ProductException{
Session session = this.hibernateSessionFactory.getCurrentSession();
String hql = "FROM com.esp.dao.entity.Product P WHERE P.isbn13 = :isbn13";
Query query = session.createQuery(hql);
query.setParameter("isbn13",isbn);
List<Product> productList = query.list(); // Want to mock this call
if(productList.size() ==1)
return productList.get(0);
else if(productList.size() >1)
// throw new ProductException("Cannot return product. Multiple products found.", HttpServletResponse.SC_NOT_FOUND);
throw new ProductException("Cannot return product. Multiple products found.");
else if(productList.size() == 0){
throw new ProductException("Cannot return product. No products found.");
}
return null;
}
我想模拟 query.list() 方法。到目前为止,这是我尝试过的但出现异常:Type 'SessionFactory' 是一个接口,无法对其进行监视。
@RunWith(MockitoJUnitRunner.class)
public class TestProductDaoImpl {
@Spy
private SessionFactory hibernateSessionFactory;
@InjectMocks
private ProductDAOImpl productDAOImpl;
@Test
public void testGetProduct() throws ProductException {
Session session = this.hibernateSessionFactory.getCurrentSession();
String hql = "";
Query query = session.createQuery(hql);
Query spy = Mockito.spy(query);
List<Product> productList = getProductList();
doReturn(productList).when(spy).list();
productDAOImpl.getProduct("abc");
}
我可以模拟 getProductFromDb()。但在那种情况下,没有必要为此编写测试用例,因为 class 的最大部分正在被模拟。
我认为有两种方法:
第一个: 像这样在 SessionFactory 上创建模拟
@Mock
private SessionFactory hibernateSessionFactory;
@Before
public void beforeTest(){
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetProduct() throws ProductException {
//then mock all you need from hibernateSessionFactory
Session session = Mockito.mock(Session.class);
Query query = Mockito.mock(Query.class);
Mockito.when(hibernateSessionFactory.getCurrentSession()).thenReturn(session);
Mockito.when(session.createQuery("FROM com.esp.dao.entity.Product P WHERE P.isbn13 = :isbn13")).thenReturn(query);
List<Product> productList = new ArrayList<>(1);
Mockito.when(query.list()).thenReturn(productList);
其次:您应该创建 SessionFactory 的实例
private SessionFactory hibernateSessionFactory;
@Before
public void beforeTest(){
hibernateSessionFactory = Mockito.spy(new ConstructorForSessionFactory ());
}