2012-02-13 14 views
5

que tienen una prueba de unidad DAO que se declara como sigue:¿Cuál es la diferencia entre @Autowired y obtener un bean del contexto de la aplicación?

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

Cuando ejecuto la prueba unitaria, todo pasa y puedo ver la db siendo recreada en el medio ejecuciones de pruebas unitarias.

Mi db prueba se define de la siguiente manera:

<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> 

Pero cuando cambio mi prueba a utilizar @Autowired, se define a continuación, que no ejecuta los scripts de inicio 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; 

No veo cuál es la diferencia. Tengo dos applicationContext.xmls, uno en el principal y el otro en la prueba (para poder anular el db con la prueba db)

Para mí, debería ejecutar lo mismo. ¿Me estoy perdiendo de algo?

Gracias,

+0

¿Dónde se define su IRegisterDao en el archivo xml? puedes por favor compartir eso? – Nomad

Respuesta

6

Por defecto, un contexto primavera no hagan caso a @Autowired anotaciones. Para procesarlos, el contexto debe tener un bean AutowiredAnnotationBeanPostProcessor registrado en el contexto.

<context:annotation-config/> 

uno de estos registros para usted (junto con algunos otros), por lo que lo necesita (a menos que se registre AutowiredAnnotationBeanPostProcessor mismo, lo cual es perfectamente válido).

Si no le gusta tener @Autowired en su código, puede inyectar propiedades explícitamente en el XML usando, que simplemente mueve el desorden de un lugar a otro.

Si su contexto es extremadamente simple, puede usar el autovínculo implícito, como se describe en here. Esencialmente, esto le dice a Spring que se autoajuste automáticamente por nombre o tipo de propiedad. Esto requirió muy poca configuración, pero se sale de control muy rápidamente: su naturaleza automática significa que es difícil de controlar y ofrece muy poca flexibilidad.

En general @Autowired es realmente la mejor opción.

Con el contexto de la aplicación, usted está inyectando el frijol usted mismo.

El cableado de anotación no está activado en el contenedor Spring por defecto. Por lo tanto, antes de que pueda usar el autoenlace basado en anotaciones, deberá habilitarlo en su configuración de Spring. La forma más sencilla de hacerlo es con la esperanza

<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> 

esto ayuda.

+0

Ambos contextos de aplicación usan esa '' configuración pero todavía encontré la discrepancia. Estaba pensando en sus líneas también ... razón por la cual estoy confundido sobre por qué hace la diferencia. – Eric

+0

@Eric, esto podría ayudar a su causa también. http://hamletdarcy.blogspot.com/2008/12/autowired-junit-tests-with-spring-25.html – Nomad

0

Estos dos escenarios son muy diferentes: en el primer caso, usted tiene DOS contextos de aplicación: uno creado por el marco de primavera de prueba y otro creado manualmente por usted para cada prueba. El marco de prueba de Spring utiliza @ContextConfiguration para determinar qué archivos de contexto se van a cargar. Si las pruebas posteriores utilizan los mismos archivos de contexto, el contexto no se vuelve a crear, se reutiliza.Es por eso que su base de datos se inicializa solo una vez si no crea adicionalmente un nuevo contexto manualmente.

Si necesita reiniciar la base de datos para cada prueba, debe activarla manualmente, por ejemplo, en el método @Before. También puede probar la anotación @DirtiesContext en su prueba, al lado de @ContextConfiguration.

Para dejar en claro: no debe crear contexto manualmente si utiliza Spring Test Framework. @Autowired es el enfoque correcto, pero debe encontrar otros medios para reiniciar su base de datos antes de cada prueba.

Cuestiones relacionadas