java - Spring Autowiring 在正在测试的类中不起作用

标签 java hibernate spring dependency-injection junit4

我正在尝试对我正在编写的 Web 服务中使用的部分代码运行高级测试。在此过程中,代码预计会调用数据库(我使用 Spring 和 Hibernate 设置了该数据库)。 Autowiring 在测试用例类本身中工作正常,但由于运行测试而调用的其他类没有被 Autowiring 。

单元测试

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

单例日志助手

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 中的 Autowiring DAO 始终以 null 结束。但是,如果我直接在单元测试中 Autowiring 它,它就会被注入(inject)到准备好的实体管理器中。当然,我担心的是,如果它在测试中不起作用,那么在正确部署后它也不会起作用。即使我不必担心这一点,我仍然想测试一下。

最佳答案

DBLogger 不是 spring bean,因此 spring 无法将任何类 Autowiring 到它(因为它不知道)。我建议将它定义为 spring 上下文中的 bean,并将 DbLogHelper 注入(inject)到您想要使用它的任何类中。

关于java - Spring Autowiring 在正在测试的类中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6350134/

相关文章:

java - 如何仅在基于数据提供者的输入运行所有测试后删除数据?

java - 为什么我的并发程序比顺序版本慢?

java - String 类型的 strip() 方法未定义

java - 如何使用 Hibernate 为有序列表创建映射文件?

java - 如何将 spring.cloud.stream.kafka.bindings 配置属性应用于所有消费者

java - Hibernate 连接数据库中的每个表

java - 只读模式下不允许写入操作 - 持续存在时出现问题

java - 如何在jpa/hibernate中实现这个简单的关联

java - 如何通过基于 Java 的配置在 Hibernate 中的查询上使用分页

spring - 如何使用 Spring EventListener 进行 sendAndReceive ?