浏览 1366 次
|
锁定老贴子 主题:spring集成测试
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2007-01-05 关键字: spring集成测试
spring集成测试,仅仅type类型的注入?
关键字:sring集成测试 spring test框架类图: 从spring test框架类图看出,AbstractTransactionalDataSourceSpringContextTests继承了多个Abstract类,其中关键的依赖注入抽象类是 AbstractDependencyInjectionSpringContextTests API说明如下:
org.springframework.test
Class AbstractDependencyInjectionSpringContextTests
java.lang.Object
junit.framework.Assert
junit.framework.TestCase
org.springframework.test.ConditionalTestCase
org.springframework.test.AbstractSpringContextTests
org.springframework.test.AbstractSingleSpringContextTests
org.springframework.test.AbstractDependencyInjectionSpringContextTests
All Implemented Interfaces:
Test
Direct Known Subclasses:
AbstractTransactionalSpringContextTests
________________________________________
public abstract class AbstractDependencyInjectionSpringContextTests
extends AbstractSingleSpringContextTests
Convenient superclass for tests depending on a Spring context. The test instance itself is populated by Dependency Injection.
Really for integration testing, not unit testing. You should not normally use the Spring container for unit tests: simply populate your POJOs in plain JUnit tests!
This supports two modes of populating the test:
• Via Setter Dependency Injection. Simply express dependencies on objects in the test fixture, and they will be satisfied by autowiring by type.
• Via Field Injection. Declare protected variables of the required type which match named beans in the context. This is autowire by name, rather than type. This approach is based on an approach originated by Ara Abrahmian. Setter Dependency Injection is the default: set the "populateProtectedVariables" property to true in the constructor to switch on Field Injection.
Since
1.11
Via Setter Dependency Injection. Simply express dependencies on objects in the test fixture, and they will be satisfied by autowiring by type. 这句说明,在使用setter DI是默认是根据类型的,而不是name.这就有有个问题了,在事务测试中,不能通过ref来指定。 配置方式: <!-- Note the use of an inner bean for the "target" property. This ensures that there is only one instance of this bean in the factory, allowing us to use autowire by type if necessary. --> <bean id="clinic" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"><ref local="transactionManager"/></property> <property name="target"> <bean class="org.springframework.samples.petclinic.jdbc.HsqlJdbcClinic"> <property name="dataSource"><ref local="dataSource"/></property> </bean> </property> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> 如果配置方式改成:
<!-- PetClinic's central data access object: HSQL JDBC implementation -->
<!-- (only initialized when referenced by the "clinic" proxy) -->
<bean id="hsqlClinic" class="org.springframework.samples.petclinic.jdbc.HsqlJdbcClinic" lazy-init="true">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--
- Transactional proxy for PetClinic's central data access facade.
- Implements the CachingClinic management interface.
-
- Note that in a real-life app with multiple transaction proxies,
- you will probably want to use parent and child bean definitions
- as described in the manual, to reduce duplication.
-->
<bean id="clinic" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref=" hsqlClinic "/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Junit控制台抛出: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.samples.petclinic.jdbc.JdbcClinicTests': Unsatisfied dependency expressed through bean property 'clinic': There are 3 beans of type [org.springframework.samples.petclinic.Clinic] available for autowiring by type: [hsqlClinic, mysqlClinic, clinic]. There should have been exactly 1 to be able to autowire property 'clinic' of bean 'org.springframework.samples.petclinic.jdbc.JdbcClinicTests'. Consider using autowiring by name instead. Consider using autowiring by name instead. 安照这解释,在配置文件中指定它,by name不就 可以了 吗 ? 我们修改配置文件,指定by name <bean id="clinic" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" autowire="byName"> 汗!可以by name instead吗? 测试问题依旧!tell why ! 看看API, private int autowireMode = AUTOWIRE_BY_TYPE; setAutowireMode public final void setAutowireMode(int autowireMode) The default is "AUTOWIRE_BY_TYPE". Can be set to "AUTOWIRE_BY_NAME" or "AUTOWIRE_NO" instead 问题出在那里呢?到这里我头大的很啊!这不是搞人吗?抱怨是没有用的,解决问题先! 有可能在读取配置文件的时候没有调用setAutowireMode方法,那就只有手动解决了。 自己写一个MyTest来手动指定 autowire by name. 代码如下:
public class DependencyInjectionTestByName extends AbstractTransactionalDataSourceSpringContextTests{
@Override
protected ConfigurableApplicationContext loadContext(Object key) throws Exception {
setAutowireMode(AUTOWIRE_BY_NAME);
setDefaultRollback(false);
return super.loadContext(key);
}
然后让测试类extends.问题解决。我正高兴了?why 有两个测试未通过! 原来是jdbcTemplate的编译错误,追踪查看,发现
/**
* Setter: DataSource is provided by Dependency Injection.
* @param dataSource
*/
public void setDataSource(DataSource dataSource) {
// TODO what if you want to use a JdbcTemplate by preference,
// for a native extractor?
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
个中滋味,只的无语啊!看来只能修改,测试abstract了。这么说来在测试中就无法调用springDAO, 注释掉使用jdbcTemplate.问题很不爽的解决。因此,在测试中,不应产生新的依赖,如:jdbcTemplate
assertEquals("JDBC query must show the same number of vets",
jdbcTemplate.queryForInt("SELECT COUNT(0) FROM VETS"),
vets.size()); 后记: spring为什么要这样做,还是一个bug. 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |


