2012-09-27 38 views
48

En primer lugar, he encontrado muchos hilos en StackOverflow sobre esto, pero ninguno de ellos realmente me ayudó, así que lamento preguntar posiblemente una pregunta duplicada.Revertir la transacción después de @Test

estoy corriendo pruebas JUnit utilizando la primavera-test, mi código es el siguiente

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {}) 
public class StudentSystemTest { 

    @Autowired 
    private StudentSystem studentSystem; 

    @Before 
    public void initTest() { 
    // set up the database, create basic structure for testing 
    } 

    @Test 
    public void test1() { 
    }  
    ... 
} 

Mi problema es que quiero que mis pruebas a no influye en otras pruebas. Entonces me gustaría crear algo así como deshacer para cada prueba. He buscado mucho para esto, pero no he encontrado nada hasta el momento. estoy usando Hibernate y MySql para este

+0

¿Qué quieres decir con rollback? Limpiando la base de datos? – Gaurav

+3

estableciéndolo exactamente en el mismo estado en que estaba después de ejecutar 'initTest' –

Respuesta

84

Sólo tiene que añadir @Transactional anotación en la parte superior de su prueba:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"testContext.xml"}) 
@Transactional 
public class StudentSystemTest { 

Por defecto primavera se iniciará una nueva transacción que rodea a su método de prueba y @Before/@After devoluciones de llamada, hacer retroceder al final. Funciona de manera predeterminada, es suficiente tener algún administrador de transacciones en el contexto.

Desde: 10.3.5.4 Transaction management (el mío negrita):

En el marco TestContext, las transacciones son gestionadas por el TransactionalTestExecutionListener. Tenga en cuenta que TransactionalTestExecutionListener es configurado de manera predeterminada, incluso si no declara explícitamente @TestExecutionListeners en su clase de prueba. Sin embargo, para habilitar el soporte para las transacciones, debe proporcionar un bean PlatformTransactionManager en el contexto de la aplicación cargado por la semántica @ContextConfiguration. Además, debe declarar @Transactional a nivel de clase o método para sus pruebas.

+0

, intenté esto antes, y todavía no funciona, tal vez ... ¿puede ser que el problema no sea definir PlatformTransactionManager, cómo ¿Puedo hacer eso? –

+0

@javo: ¿cómo estás modificando la base de datos? Si está utilizando Jpa/Hibernate/JdbcTemplate/... debe haber algún 'PlatformTransactionManager'. De lo contrario, ¿cómo sabrá Spring sobre sus transacciones y su base de datos? –

+0

El enlace en esta respuesta ya no es correcto; vea [la respuesta del usuario2418306 a continuación] (http://stackoverflow.com/a/35943700/325900) para obtener el enlace correcto y más contexto de la documentación de Spring. – DaveyDaveDave

0

Tiene que ejecutar la prueba con un contexto de sprint y un administrador de transacciones, por ejemplo,

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"/your-applicationContext.xml"}) 
@TransactionConfiguration(transactionManager="txMgr") 
public class StudentSystemTest { 

    @Test 
    public void testTransactionalService() { 
     // test transactional service 
    } 

    @Test 
    @Transactional 
    public void testNonTransactionalService() { 
     // test non-transactional service 
    } 
} 

Véase el capítulo 10. Testing de la referencia de la primavera para más detalles.

8

Las respuestas mencionan la adición de @Transactional son correctas, pero por simplicidad sólo podría tener su clase de prueba extends AbstractTransactionalJUnit4SpringContextTests.

+0

agregar anotación '@Transactional' en el nivel de clase no funciona, agregar anotación '@Transactional' por separado para cada función funciona, y extiende AbstractTransactionalJUnit4SpringContextTests funciona también – user3871754

-5

Puede desactivar el Rollback:

@TransactionConfiguration(defaultRollback = false) 

Ejemplo:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class) 
@Transactional 
@TransactionConfiguration(defaultRollback = false) 
public class Test { 
    @PersistenceContext 
    private EntityManager em; 

    @org.junit.Test 
    public void menge() { 
     PersistentObject object = new PersistentObject(); 
     em.persist(object); 
     em.flush(); 
    } 
} 
+3

Eso es exactamente lo opuesto a lo que pide el OP –

2

me conocen, soy demasiaaaado tarde para publicar una respuesta, pero con la esperanza de que podría ayudar a alguien. Además, acabo de resolver este problema que tuve con mis pruebas. Esto es lo que tenía en mi prueba:

Mi clase de prueba

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "path-to-context" }) 
@Transactional 
public class MyIntegrationTest 

Contexto xml

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="${jdbc.driverClassName}" /> 
    <property name="url" value="${jdbc.url}" /> 
    <property name="username" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
</bean> 

todavía tenía el problema de que, la base de datos no estaba siendo limpiado automáticamente.

problema se resolvió cuando he añadido a la siguiente propiedad BasicDataSource

<property name="defaultAutoCommit" value="false" /> 

espero que ayude.

+0

Bueno, ¿así que compromete sus estados de cuenta manualmente? ¿Estás seguro de que tus datos fueron escritos en tu base de datos? –

11

Aparte: fue rechazado intento de modificar la respuesta de Tomasz Nurkiewicz:

Esta edición no hace que el mensaje aunque sea un poco más fácil de leer, fácil de encontrar, más precisa o más accesible. Los cambios son completamente superfluos o perjudican activamente la legibilidad.


correcta y permanente link a la sección correspondiente de la documentación sobre las pruebas de integración.

Para activar el soporte de transacciones, debe configurar un grano PlatformTransactionManager en el ApplicationContext que se carga a través de @ContextConfiguration semántica.

 
@Configuration 
@PropertySource("application.properties") 
public class Persistence { 
    @Autowired 
    Environment env; 

    @Bean 
    DataSource dataSource() { 
     return new DriverManagerDataSource(
       env.getProperty("datasource.url"), 
       env.getProperty("datasource.user"), 
       env.getProperty("datasource.password") 
     ); 
    } 

    @Bean 
    PlatformTransactionManager transactionManager() { 
     return new DataSourceTransactionManager(dataSource()); 
    } 
} 

Además, debe declarar @Transactional anotación de la primavera, ya sea a nivel de clase o método para sus pruebas.

 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = {Persistence.class, SomeRepository.class}) 
@Transactional 
public class SomeRepositoryTest { ... } 

Anotación de un método de ensayo con @Transactional hace que la prueba que se ejecuta dentro de una transacción que, por defecto, automáticamente se deshace después de la finalización de la prueba. Si una clase de prueba se anota con @Transactional, cada método de prueba dentro de esa jerarquía de clase se ejecutará dentro de una transacción.

Cuestiones relacionadas