【问题标题】:How to mock Hibernate Query.list() using Mockito如何使用 Mockito 模拟 Hibernate Query.list()
【发布时间】:2016-07-14 08:26:54
【问题描述】:

这是我需要测试的课程:

@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()。但在这种情况下,没有必要为此编写测试用例,因为该类的大部分内容都被嘲笑了。

【问题讨论】:

    标签: spring unit-testing mockito powermock powermockito


    【解决方案1】:

    我认为有两种方法:

    第一: 像这样在 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 ());
    }
    

    【讨论】:

    • 对不起。我刚刚编辑了我的问题。我需要模拟 Query.list() 方法。为此,在我的测试类中,我需要创建一个有效的 Query 对象然后对其进行模拟。但在这里我无法模拟 Query 对象。
    • @Sumit Pal。你没有错误'类型'SessionFactory'是一个接口,它不能被监视'并且只有'query.list()'有问题?
    • 我有这个错误。通过应用您的解决方案 1 它解决了 & 现在我在 session.createQuery(hql);
    • 我监视 hibernateSessionFactory 的原因是 hibernateSessionFactory 在 ProductDAOImpl 中是自动连线的。但我还需要一个真正的 hibernateSessionFactory 对象来在测试类中创建 Query 对象(以便我可以模拟它)。如果我错了,请纠正我。我是 Mockito 的新手
    • 谢谢!!。我不知道我们可以像 Mockito.mock(Session.class);我认为我们必须在 Mockito.mock() 中传递一个有效的 Session 对象。 :)
    猜你喜欢
    • 1970-01-01
    • 2016-05-08
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多