如何使用 Mockito 模拟 Hibernate Query.list()



这是我需要测试的类:

@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() 方法。这是我到目前为止尝试过的,但出现异常:类型"会话工厂"是一个接口,无法监视。

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

在我看来有两种方法:

第一:像这样在会话工厂上创建模拟

@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);

第二:你应该创建会话工厂的实例

private SessionFactory hibernateSessionFactory;
@Before
public void beforeTest(){
    hibernateSessionFactory = Mockito.spy(new ConstructorForSessionFactory ());
}

我们可以对Hibernate query.list执行单元测试。 如果我们有以下方法从数据库中获取结果列表:

private List<?> getTxns(String sql) {
    Session session = null;
    try {
        session = ht.getSessionFactory().openSession();
        Query q = session.createSQLQuery(sql).addEntity(Entity.class);
        return q.list();
    } catch (Exception e) {
        log.error(sql, e);
    } finally {
        daoUtil.closeSession(sql, session);
    }
    return new ArrayList();
}

然后我们可以编写以下方式进行单元测试:

@BeforeEach
public void setup() {
    SessionFactory sessionFactory = mock(SessionFactory.class);
    hibernateTemplate = mock(HibernateTemplate.class);
    when(daoUtil.getWritableHT()). thenReturn(hibernateTemplate);
    when(hibernateTemplate.getSessionFactory()).thenReturn(sessionFactory);
    Session session= mock(Session.class);
    when(sessionFactory.openSession()).thenReturn(session);
    SQLQuery sqlQuery=mock(SQLQuery.class);
    when(session.createSQLQuery(any())).thenReturn(sqlQuery);
    when(sqlQuery.addEntity(Entity.class)).thenReturn(sqlQuery);
    Entity entity = new Entity();
    List<Entity> entityList= new ArrayList<>();
    entityList.add(txn);
    when(sqlQuery.list()).thenReturn(entityList);
}
 @Test
void getTxn_list() {
    //Arrange and Assert
    Assert.assertEquals(1,object.getTxns(query).size());
}

最新更新