我有一个dao单元测试,声明如下:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/applicationContext.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
public class RegisterDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:/spring/applicationContext.xml");
private IRegisterDao registerDao = applicationContext.getBean(IRegisterDao.class);
当我运行单元测试时,所有通过,我可以看到在单元测试执行之间重新创建数据库。
我的测试数据库定义如下:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:test;sql.syntax_ora=true;create=true"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
<jdbc:script location="file:Artifacts/Hsql Version Scripts/install/droptables.sql" separator=";"/>
<jdbc:script location="file:Artifacts/Hsql Version Scripts/install/install.sql" separator="/;"/>
</jdbc:initialize-database>
但是当我将测试更改为使用@Autowired(定义如下)时,它不会执行init db脚本。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/applicationContext.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
public class RegisterDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
/*
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:/spring/applicationContext.xml");
private IRegisterDao registerDao = applicationContext.getBean(IRegisterDao.class);
*/
@Autowired
private IRegisterDao registerDao;
我看不出有什么区别。我有两个applicationContext.xmls,一个在main中,一个在测试中(所以我可以用测试db覆盖db)
对我来说,它应该执行相同的操作。我错过了什么吗?
谢谢,
答案 0 :(得分:7)
默认情况下,Spring上下文不会关注 @Autowired 注释。为了处理它们,上下文需要在上下文中注册 AutowiredAnnotationBeanPostProcessor bean。
<context:annotation-config/>
为你注册其中一个(以及其他一些),所以你确实需要它(除非你自己注册 AutowiredAnnotationBeanPostProcessor ,这是完全有效的。)
如果您不想在代码中使用 @Autowired ,那么您可以使用XML显式地注入属性,这只会将混乱从一个地方移动到另一个地方。
如果您的上下文非常简单,那么您可以使用隐式自动装配,如here所述。从本质上讲,这告诉Spring按属性名称或类型自动自动装配。这需要很少的配置,但它很快失控 - 它的自动性意味着它难以控制,并且给你很小的灵活性。
一般来说, @Autowired 确实是最好的选择。
使用应用程序上下文,您可以自己注入bean。
默认情况下,Spring容器中未打开注释接线。所以,在你之前 可以使用基于注释的自动装配,您需要在Spring配置中启用它。 最简单的方法是使用
<context:annotation-config>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
...
</beans>
希望这有帮助。
答案 1 :(得分:0)
这两种情况非常不同:在第一种情况下,您有两个应用程序上下文:一个由测试弹簧框架创建,另一个由您为每个测试手动创建。 Spring测试框架使用@ContextConfiguration来确定要加载的上下文文件。如果后续测试使用相同的上下文文件,则不会重新创建上下文,而是重用它。这就是为什么如果不另外手动创建新上下文,则只初始化数据库一次。
如果确实需要为每个测试重新初始化db,则应该手动触发它,例如在@Before
方法中。您也可以在@DirtiesContext
旁边的测试中尝试注释@ContextConfiguration
。
说清楚:如果使用spring测试框架,则不应手动创建上下文。 @Autowired
是正确的方法,但您需要找到其他方法在每次测试之前重新初始化您的数据库。