gpt4 book ai didi

java - 使用Mockito模拟spring的LocalContainerEntityManagerFactoryBean方法?

转载 作者:行者123 更新时间:2023-12-02 03:27:57 27 4
gpt4 key购买 nike

我正在尝试为以下代码编写单元测试用例,并尝试模拟 EntityManager 实现。我无法这样做,并且我在测试类中得到空实体管理器 bean。

public List<Object[]> getForecastResults(String query, String siteId, long startTime, long endTimestamp)
{
List<Object[]> result = null;
EntityManager em = null;
try {
query = String.format(query, startTime, endTimestamp, siteId);
logger.debug(" Query : " + query);
em = localContainerEntityManagerFactoryBean.nativeEntityManagerFactory.createEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
result = (List<Object[]>) em.createNativeQuery(query).getResultList();
//logger.debug("Results from the query : " + query + " are :" + Utility.toJsonString(result, true));
} catch (Exception ex) {
ex.printStackTrace();
logger.error("Error Occurred while fetching the data for the query : " + query);
}
return result;
}

我编写的模拟它的测试代码如下:

@InjectMocks
private LocalContainerEntityManagerFactoryBean emMock = new LocalContainerEntityManagerFactoryBean();

...

Mockito.when(localContainerEntityManagerFactoryBean.nativeEntityManagerFactory.createEntityManager()).thenReturn();

当这被称为输出时我应该返回一个列表所以我需要模拟整个方法。请帮忙!

最佳答案

首先全部代替 @InjectMocks你应该使用@Mock并输入 @InjectMocks在您尝试进行单元测试的类(class)上。

然而,事实上您甚至正在考虑 mock LocalContainterEntityManagerFactoryBean表明您的代码有缺陷。您不应该使用 LCEMFB在代码中。它仅用于配置。这是一个FactoryBean创建 EntityManagerFactory所以实际上你应该注入(inject) EntityManagerFactory进入你应该 mock 的代码。

而不是连接 LCEMFB使用简单的EMF并通过使用 @PersistenceUnit 注释该字段来获取实例。

@PersistenceUnit
private EntityManagerFactory emf;

那么你的方法也更干净一点

public List<Object[]> getForecastResults(String query, String siteId, long startTime, long endTimestamp)
{
List<Object[]> result = null;
EntityManager em = null;
try {
query = String.format(query, startTime, endTimestamp, siteId);
logger.debug(" Query : " + query);
em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
result = (List<Object[]>) em.createNativeQuery(query).getResultList();
//logger.debug("Results from the query : " + query + " are :" + Utility.toJsonString(result, true));
} catch (Exception ex) {
ex.printStackTrace();
logger.error("Error Occurred while fetching the data for the query : " + query);
}
return result;
}

但是你实际上应该做的是注入(inject) EntityManager并且不要尝试自己创建一个(您的代码仍然有缺陷,因为您没有关闭事务,也没有创建 EntityManager ,这反过来最终会导致您无法作为底层 Connection 连接到数据库也保持开放。

因此,不要注入(inject) LCEMFBEMF使用普通 EntityManager相反,让 spring 为你管理它。要让 spring 管理事务,请确保有 @EnableTransactionManagement<tx:annotation-driven />在您的配置中,否则它将无法工作。

@PersistenceContext
private EntityManager em;

现在你的方法真正专注于它应该做的事情,从数据库获取数据。

@Transactional(readOnly=true)
public List<Object[]> getForecastResults(String query, String siteId, long startTime, long endTimestamp) {
query = String.format(query, startTime, endTimestamp, siteId);
return em.createNativeQuery(query).getResultList();
}

现在在您的测试中您应该只需要模拟 EntityManager

所有这一切也在ORM chapter中进行了解释。 Spring 引用指南。

另一件事让我担心的是您正在使用字符串并解析它以用作查询。这是潜在的危险,并且会导致 SQL injection attacks 。您应该让 Hibernate 或 JDBC 处理它,而不是自己进行格式化。

@Transactional(readOnly=true)
public List<Object[]> getForecastResults(String query, String siteId, long startTime, long endTimestamp) {
query = String.format(query, startTime, endTimestamp, siteId);
Query q = em.createNativeQuery(query);
q.setParameter("siteId", siteId)
.setParameter("startTime", startTime)
.setParameter("endTime", endTimestamp);
return q.getResultList();
}

上面的代码假设查询的形式为 SELECT * FROM YOURTABLE WHERE siteId=:siteId and startTime >= :startTime and endTime <= :endTime (或者任何你的 SQL 的样子)。

关于java - 使用Mockito模拟spring的LocalContainerEntityManagerFactoryBean方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38536010/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com