[英]Spring Autowiring not working in classes being tested
我正在嘗試對我正在編寫的 web 服務中使用的部分代碼運行高級測試。 在此過程中,代碼將調用數據庫(我使用 Spring 和 Hibernate 設置了該數據庫)。 自動裝配在測試用例 class 本身中工作正常,但由於運行測試而被調用的其他類沒有被自動裝配。
單元測試
@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration
public class ProviderTest
{
@Autowired
protected ApplicationContext applicationContext;
protected ProviderA provider;
@Before
public void setUp()
{
Transaction transaction = DbLogHelper.getInstance().getLog();
transaction.setCompanyName("Unit Test");
transaction.setCreateTime(Calendar.getInstance());
transaction.setPhoneNumber("Provider Test - N/A");
transaction.setQueryId("Unit Test");
transaction.setRequest("<NONE - UNIT TEST>");
transaction.setResponse("<NONE - UNIT TEST>");
LogJob job = new LogJob(transaction, DbLogHelper.getInstance.getDao());
job.run();
provider = new ProviderA(transaction);
}
@After
public void tearDown()
{
Transaction transaction = DbLogHelper.getInstance().getLog();
transaction.setResponseTime(Calendar.getInstance());
DbLogHelper.getInstance().writeLog(transaction);
DbLogHelper.getInstance().resetLog();
}
@Test
public void testProvider()
{
try
{
List<TAddress> results = provider.searchItem("SOME_ITEM", "12345");
Assert.assertNotNull(results);
}
catch (Exception e)
{
Assert.fail();
}
}
}
Singleton 日志助手
public class DbLogHelper
{
private static DbLogHelper instance;
@Autowired
private LogDao dao;
private Executor executor = new ThreadPoolExecutor(3, 10, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
private ThreadLocal<Transaction> transactionRef = new ThreadLocal<Transaction>() {
@Override
protected Transaction initialValue()
{
return new Transaction();
}
};
public static DbLogHelper getInstance()
{
if (instance == null)
{
synchronized (DbLogHelper.class)
{
if (instance == null)
{
instance = new DbLogHelper();
}
}
}
return instance;
}
/**
* Gets the Transaction object attached to this thread. Generates a new one if it does not
* yet exist.
* @return Transaction
*/
public Transaction getLog()
{
return transactionRef.get();
}
/**
* Removes the current Transaction object from the thread map. The next getLog() call will
* generate a new one.
*/
public void resetLog()
{
transactionRef.remove();
}
/**
* Gets the DAO used to persist Transaction objects
*/
public LogDao getDao()
{
return dao;
}
/**
* Queues the passed Transaction object to be written to the database. This happens in a
* separate thread so the service is not waiting on database persistence before responding.
* @param transaction
*/
public void writeLog(Transaction transaction)
{
LogJob job = new LogJob(transaction, dao);
executor.execute(job);
}
}
記錄 DAO
@Repository
public class LogDao
{
private static Logger log = LoggerFactory.getLogger(LogDao.class);
private EntityManager entityManager;
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
log.debug("Entity Manager set on LogDao");
this.entityManager = entityManager;
}
@Transactional
public void updateTransaction(Transaction log)
{
log = entityManager.merge(log);
}
}
ProviderTest-context.xml
<!-- database -->
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<!-- uncomment to see sql
<property name="driverClassName" value="com.p6spy.engine.spy.P6SpyDriver" />
-->
<property name="url" value="jdbc:mysql://localhost" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<!-- LOCAL entity manager factory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- <property name="persistenceUnitManager" ref="persistenceUnitManager"/> -->
<property name="persistenceUnitName" value="domainPersistenceUnit" />
<property name="dataSource" ref="datasource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<!-- <property name="generateDdl" value="true" /> -->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="datasource" />
</bean>
<context:annotation-config/>
<context:component-scan base-package="com.company.application.webservice"/>
DbLogHelper 中的自動裝配 DAO 始終以 null 結尾。 但是,如果我直接在單元測試中自動裝配它,它會很好地注入實體管理器,准備好 go。 當然,我擔心的是,如果它在測試中不起作用,那么在正確部署時它也不會起作用。 即使我不必擔心這一點,我仍然想測試它。
DBLogger 不是 spring bean,因此 spring 無法將任何 class 自動連接到它(因為它不知道它)。 我建議在您的 spring 上下文中將其定義為 bean,並將 DbLogHelper 注入您想要使用它的任何 class 中。
您應該將 DBLogger 定義為 @John Vint 提到的 spring bean,或者如果由於某種原因不能,您可以獲得 object 您想從 Z2A2D595E6ED9A3B24F027F2B 應用程序上下文自動裝配(不推薦)。
有關后者的詳細信息: http://www.javacodegeeks.com/2015/03/using-spring-managed-bean-in-non-managed-object.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.