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

标签 spring unit-testing mockito powermock powermockito

这是我需要测试的类(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() 方法。这是我到目前为止所尝试过的,但出现异常:类型“SessionFactory”是一个接口(interface),无法监视它。

@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()。但在这种情况下,不需要为此编写测试用例,因为类的大部分部分都被模拟了。

最佳答案

我认为有两种方法:

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

关于spring - 如何使用 Mockito 模拟 Hibernate Query.list(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38369127/

相关文章:

c# - 使用命令式绑定(bind)时进行 Azure Functions 测试

elasticsearch - 任何 java.lang.NullPointerException 时的 Mockito

java - Mockito Java中的模拟继承方法

mysql - MySql 函数的 SimpleJdbcCall 产生 "Can' t 为存储函数调用的返回值设置 IN 参数”

java - "A component required a bean of type",但是哪一个呢?

C# ASP.NET MVC Controller 单元测试

java - 如何对调用 super 的重写方法进行单元测试?

java - 从模拟方法中的方法返回类。莫基托

java - 我们应该使用 clone 还是 BeanUtils.copyProperties 以及为什么

angularjs - 一个项目中的 Spring Rest 和 Angular JS