![](/img/trans.png)
[英]Mock Method of authowired bean using mockito and spring mock
[英]Mock spring's LocalContainerEntityManagerFactoryBean method using Mockito?
我試圖為下面的代碼編寫單元測試用例,並試圖模擬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();
當將此稱為輸出時,我應該返回一個列表,因此我需要模擬整個方法。 請幫忙 !
首先,應該使用@Mock
而不是@InjectMocks
,並將@InjectMocks
放在要進行單元測試的類上。
但是,您甚至考慮模擬LocalContainterEntityManagerFactoryBean
的事實也表明您的代碼存在缺陷。 您不應在代碼中使用LCEMFB
。 僅用於配置。 它是一個創建EntityManagerFactory
的FactoryBean
,因此實際上您應該將EntityManagerFactory
注入應該FactoryBean
的代碼中。
不用連接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;
}
但是,您實際上應該做的是注入EntityManager
並不要嘗試自己創建一個(您的代碼仍然存在缺陷,因為您沒有關閉事務,也沒有創建的EntityManager
最終將導致您無法連接到基礎數據庫的Connection
保持打開狀態。
因此,不要注入LCEMFB
或EMF
使用普通的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
。
所有這些都在Spring參考指南的ORM章節中進行了說明。
讓我擔心的另一件事是您正在使用String並將其解析為查詢。 這是潛在的危險,並且是SQL注入攻擊的原因。 而不是自己進行格式化,您應該讓它由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形式)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.