How to mock Hibernate Query.list() using Mockito
11,784
In my opinion there are two approach:
First: Create mock on SessionFactory like this
@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);
Second: You should create instance of SessionFactory
private SessionFactory hibernateSessionFactory;
@Before
public void beforeTest(){
hibernateSessionFactory = Mockito.spy(new ConstructorForSessionFactory ());
}
Related videos on Youtube
Author by
Sumit
Updated on June 04, 2022Comments
-
Sumit almost 2 years
This is my class which need to be tested:
@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; }
I want to mock the query.list() method. This is what I have tried so far but getting exception: Type 'SessionFactory' is an interface and it cannot be spied on.
@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"); }
I can mock the getProductFromDb(). But in that case there is no need to write a test case for that as the maximum part of the class is getting mocked.
-
Sumit almost 8 yearsI am sorry. I just edited my question. I need to mock the Query.list() method. For that in my test class I need to create a valid Query object & then mock it. But here I am unable to mock the Query object.
-
Evgeniy K. almost 8 years@Sumit Pal. You don't have error 'Type 'SessionFactory' is an interface and it cannot be spied on' and problem with only 'query.list()'?
-
Sumit almost 8 yearsI have that error. By applying your solution 1 it solved & now I am getting NullPointerException at line session.createQuery(hql);
-
Sumit almost 8 yearsThanks!!. I was not aware that we can mock like Mockito.mock(Session.class); I thought we have to pass a valid object of Session in Mockito.mock(). :)