2010-05-18 31 views
17

Estoy trabajando para intentar implementar una prueba JUnit para verificar la funcionalidad de un DAO. (El DAO creará/leerá una relación básica de objeto/tabla).Spring/Hibernate/Junit ejemplo de prueba DAO contra HSQLDB

El problema que estoy teniendo es la persistencia de la DAO (para el código no prueba) se está completando a través de una solución interna usando Primavera/Hibernate, lo que elimina las habituales *.hbm.xml plantillas que la mayoría de los ejemplos I han encontrado contener.

Debido a esto, estoy teniendo algunos problemas para entender cómo configurar una prueba JUnit para implementar el DAO para crear/lectura (solo una funcionalidad muy básica) a un HSQLDB en memoria . He encontrado algunos ejemplos, pero el uso de la persistencia interna significa que no puedo extender algunas de las clases que muestran los ejemplos (parece que no puedo obtener la configuración de la aplicación-contexto.xml correctamente).

¿Alguien puede sugerir algún proyecto/ejemplo que pueda ver (o cualquier documentación) para comprender mejor la mejor manera de implementar esta funcionalidad de prueba? Siento que esto debería ser realmente simple, pero sigo teniendo problemas para implementar los ejemplos que he encontrado.

edición:

Aquí está mi solución para una mejor legibilidad, para cualquier persona que necesita una mano que las cosas se van:

  • Mi TestClass:

    @RunWith(SpringJUnit4ClassRunner.class) 
    @ContextConfiguration(locations = "classpath:applicationContextTest-Example.xml") 
    @Transactional 
    public class ExampleDaoTest extends AbstractTransactionalJUnit4SpringContextTests { 
        @Resource(name = "sessionFactory") 
        private SessionFactory exampleSessionFactory; 
    
        @Resource(name = "exampleDao") 
        private ExampleDao exampleDao; 
    
  • Mi archivo applicationContext.xml :

    <!-- List of Daos to be tested --> 
    <bean id="exampleDao" class="org.myExample.ExampleDao"/> 
    
    <!-- Datasource --> 
    <bean id="example_dataSource" 
         class="org.apache.commons.dbcp.BasicDataSource"> 
        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> 
        <property name="url" value="jdbc:hsqldb:mem:ExampleTest"/> 
        <property name="username" value="sa"/> 
        <property name="password" value=""/> 
    </bean> 
    
    <!-- Session Factory --> 
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
        <property name="dataSource" ref="example_dataSource"/> 
        <property name="annotatedClasses"> 
         <list> 
          <value>org.myExample.ExampleClass</value> 
         </list> 
        </property> 
        <property name="hibernateProperties"> 
         .... left to user to choose properties 
        </property> 
    </bean> 
    
+0

Alguna información adicional: no estoy muy experimentado con la configur de Spring/Hibernate, ya los he configurado en proyectos anteriores hasta ahora. Mi proyecto actual es una mezcolanza de configuraciones, no puedo entender cómo la clase "interna" a la que me refiero obtiene su fábrica de sesiones. Todos los DAO lo extienden (una clase abstracta), y dentro hay una declaración abstracta: public sessionFactory getSessionFactory(); No puedo averiguar de dónde viene el método "getSessionFactory()". Creo que debe ser inyectado por Spring de alguna manera, pero no puedo encontrar ningún archivo de configuración. –

+0

Gracias muchachos, todos han sido útiles. Para aquellos en el futuro: Incluí en mi prueba de unidad (a través de @ContextConfiguration como especifica Willie) mi archivo applicationContext-Test.xml en el que definí un origen de datos HSQLDB, fábrica de sesiones, administrador de transacciones y Daos como beans . Mi clase Test está anotada con: @RunWith (SpringJUnit4ClassRunner.class), @ContextConfiguration (locations = "su appContext.xml") @Transactional, y mi sesión factory & dao están anotados como recursos (desde .xml defs): @ Recurso (name = "sessionFactory") –

Respuesta

5

Spring 3 ofrece un nuevo espacio de nombres jdbc que incluye soporte para bases de datos incrustadas, incluyendo HSQLDB. Entonces eso cuida de esa parte.

Me pregunto cuál podría ser la "solución interna". Puede usar anotaciones (anotaciones JPA o Hibernate) para ORM sus objetos de dominio, entonces ¿por qué necesita una "solución interna"? P.ej.:

<bean id="sessionFactory" 
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" 
    p:dataSource-ref="dataSource" 
    p:packagesToScan="myapp.model" /> 

En lo que respecta a la implementación de una prueba, utilice Spring's TestContext Framework. Una prueba puede tener este aspecto (de nuevo Asumo la primavera 3 a continuación, a pesar de que debería funcionar en la primavera de 2,5 simplemente cambiando @Inject a @Autowired):

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({ 
    "/beans-datasource-it.xml", 
    "/beans-dao.xml", 
    "/beans-service.xml", 
    "/beans-web.xml" }) 
@Transactional 
public class ContactControllerIT { 
    @Inject private ContactController controller; 

    ... setUp() and tearDown() ... 

    @Test 
    public void testGetContact() { 
     String viewName = controller.getContact(request, 1L, model); 

     ... assertions ... 
    } 
} 

que había puesto la base de datos incrustada en el interior beans-datasource-it.xml, por ejemplo. ('aquí' significa prueba de integración, y los archivos están en classpath.) El controlador en este ejemplo vive en beans-web.xml, y se autoconectará en el campo ContactController.

Eso es solo un resumen de qué hacer, pero espero que sea suficiente para comenzar.

1

La línea de fondo con Hibernate es la SessionFactory - su solución en la casa lo más probable es ser la creación de uno de ellos de alguna manera. Averigüe cómo, y luego agregue un bean para crear uno en el contexto de su aplicación de prueba de la misma manera (o si es posible usando su código interno que se usa en tiempo de ejecución). Es posible que deba crear su propio FactoryBean para realizar la creación de instancias. (Use AbstractFactoryBean como su clase base.)

Una vez que esto esté en su lugar, la mayoría de los ejemplos que usan LocalSessionFactoryBean se pueden migrar a su situación: en lugar de utilizar LocalsessionFactoryBean, use su bean de fábrica personalizado.

(Si no lo has hecho, mira la sección de Testing en la referencia de la primavera -. Que hace que las pruebas con la primavera, y la inyección de pruebas con frijoles desde el contexto de una brisa)

2

See here. Asume maven2 como herramienta de compilación, pero puedes usar cualquier cosa fácilmente.

+0

@downvoter - ¿fue porque me vinculé a mi blog? – Bozho

0

Mi contexto de aplicación se ve un poco diferente

<beans:bean class="org.apache.commons.dbcp.BasicDataSource" id="HSQL_DS"> 
    <beans:property name="driverClassName" value="org.hsqldb.jdbcDriver"/> 
    <beans:property name="url" value="jdbc:hsqldb:mem:Test"/> 
    <beans:property name="username" value="sa"/> 
    <beans:property name="password" value=""/> 
</beans:bean> 
<jdbc:embedded-database id="HSQL_DS"> 
    <jdbc:script location="classpath:schema.sql"/> 
    <jdbc:script location="classpath:data.sql"/> 
</jdbc:embedded-database> 

y mi clase de prueba es el siguiente:

public class Tester { 

    private EmbeddedDatabase db; 

    @Before 
    public void setUp(){ 
     db = new EmbeddedDatabaseBuilder().addDefaultScripts().build(); 


    } 

    @Test 
    public void TestMe(){ 
     System.out.println("Testing"); 
    } 


    @After 
    public void tearDown(){ 

     db.shutdown(); 
    } 
}