2010-11-12 22 views
34

No tengo problemas para probar mi DAO y mis servicios, pero cuando pruebo INSERT s o UPDATE s, quiero deshacer la transacción y no afectar a mi base de datos.Cómo revertir una transacción de base de datos cuando se prueban servicios con Spring en JUnit?

Estoy usando @Transactional dentro de mis servicios para administrar transacciones. Quiero saber si es posible saber si una transacción estará bien, pero si la revierte para evitar la alteración de la base de datos.

Esta es mi prueba:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml") 
@TransactionConfiguration(defaultRollback=true) 
public class MyServiceTest extends AbstractJUnit38SpringContextTests { 
    @Autowired 
    private MyService myService; 

    @BeforeClass 
    public static void setUpClass() throws Exception { 
    } 

    @AfterClass 
    public static void tearDownClass() throws Exception { 
    } 

    @Test 
    public void testInsert(){ 
     long id = myService.addPerson("JUNIT"); 
     assertNotNull(id); 
     if(id < 1){ 
      fail(); 
     } 
    } 
} 

El problema es que esta prueba fallará porque transacción se rollback, pero el inserto está bien! Si elimino @TransactionConfiguration(defaultRollback=true), pase la prueba pero se insertará un nuevo registro en la base de datos.

@Test 
@Transactional 
@Rollback(true) 
public void testInsert(){ 
    long id = myService.addPerson("JUNIT"); 
assertNotNull(id); 
if(id < 1){ 
     fail(); 
    } 
} 

Ahora se puede probar la aprobación correctamente, pero se ignora la reversión y el registro se inserta en la base de datos. He anotado el método addPerson() dentro de myService con @Transactional, obviamente. ¿Por qué se ignora la reversión?

+0

buena pregunta +1 :-) –

Respuesta

28

Es necesario extender los límites de transacción a los límites de su método de ensayo. Puede hacerlo mediante la anotación de su método de prueba (o toda la clase de prueba) como @Transactional:

@Test 
@Transactional 
public void testInsert(){ 
    long id=myService.addPerson("JUNIT"); 
    assertNotNull(id); 
    if(id<1){ 
     fail(); 
    } 
} 

También puede utilizar este enfoque para asegurar que los datos se escribió correctamente antes de deshacer:

@Autowired SessionFactory sf; 

@Test 
@Transactional 
public void testInsert(){ 
    myService.addPerson("JUNIT"); 
    sf.getCurrentSession().flush(); 
    sf.getCurrentSession().doWork(... check database state ...); 
} 
+0

hola, ahora paso de prueba, pero se ignoró la reversión. Tengo @Transactional sobre "testAddPerson" y sobre "addPerson". – blow

+0

Si elimino @Transactional de myService, no hay una transacción activa para la prueba, por lo que creo que @Transactional sobre "testAddPerson" no funciona ... – blow

+5

@blow: Me di cuenta de que tienes 'extends AbstractJUnit38SpringContextTests'. No es necesario ya que tiene una prueba JUnit 4 con '@ RunWith'. – axtavt

2

la salida

http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

Sección 8.3.4, en particular

primavera tiene algunas clases para las pruebas, que envolverá cada prueba en una transacción, por lo que la base de datos no se cambia. Puede cambiar esa funcionalidad si lo desea también.

Editar - basado en sus más infos, es posible que desee ver en

AbstractTransactionalJUnit38SpringContextTests en

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/context/junit38/AbstractTransactionalJUnit38SpringContextTests.html

+0

hola tuve más información. – blow

+0

@blow - actualicé mi respuesta. – hvgotcodes

+0

gracias, esto es útil, encontré un pequeño problema en mi implementación. Ahora tengo otro problema, la reversión se ignora – blow

0

Si su

myService.addPerson("JUNIT"); 

método se anota como @Transactional que va a obtener algún tipo diferente o errores tratando de arreglar esto. Así que mejor prueba los métodos DAO.

1

Uso siguiente anotación antes de la clase:

@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true) 
@Transactional 

aquí txManager es administrador de transacciones de contexto de aplicación.

Aquí txManager es una instancia o identificación de frijol del administrador de transacciones de application context.

<!-- Transaction Manager --> 
    <bean id="txManager" 
      class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="txManager" /> 

Añadir el código dentro de setUp() método, esto va a ejecutar en el inicio de la prueba y la última recapitulación debe ser puesto en teatDown() método que se ejecuta en el último código. o también puede usar la anotación @Before y @After en lugar de ella.

Cuestiones relacionadas