unitarias tutorial pruebas proyecto mvc framework español crear spring junit transactions hsqldb

spring - tutorial - ¿Cómo puedo restablecer el estado de mi base de datos después de cada prueba de unidad sin hacer que toda la prueba sea una transacción?



spring security tutorial español pdf (4)

@DirtiesContext no fue una solución para mí porque todo el contexto de la aplicación se destruye y se debe crear después de cada prueba -> Se demora mucho.

@Antes tampoco fue una buena solución para mí, ya que tengo que crear @Antes en cada examen de integración

Así que decidí crear un TestExecutionListener que recrea la base de datos después de cada prueba. (Con liquibase, pero también funciona con rutas de vuelo y sql normal)

public class CleanupDatabaseTestExecutionListener extends AbstractTestExecutionListener { public final int getOrder() { return 2001; } private boolean alreadyCleared = false; @Override public void prepareTestInstance(TestContext testContext) throws Exception { if (!alreadyCleared) { cleanupDatabase(testContext); alreadyCleared = true; } else { alreadyCleared = true; } } @Override public void afterTestClass(TestContext testContext) throws Exception { cleanupDatabase(testContext); } private void cleanupDatabase(TestContext testContext) throws LiquibaseException { ApplicationContext app = testContext.getApplicationContext(); SpringLiquibase springLiquibase = app.getBean(SpringLiquibase.class); springLiquibase.setDropFirst(true); springLiquibase.afterPropertiesSet(); //The database get recreated here } }

Para usar el TestExecutionListenere he creado una anotación de prueba personalizada

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @RunWith(SpringRunner.class) @SpringBootTest(classes = OurderApp.class) @TestExecutionListeners(mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS, listeners = {CleanupDatabaseTestExecutionListener.class} ) public @interface OurderTest { }

Por último, pero no menos importante, ahora puedo crear pruebas y puedo estar seguro de que la base de datos está en un modo limpio.

@RunWith(SpringRunner.class) @OurderTest public class ProductSaveServiceIntTest { }

Estoy usando Spring 3.1.1.RELEASE, Hibernate 4.1.0.Final, JPA 2, JUnit 4.8.1 y HSQL 2.2.7. Quiero ejecutar algunas pruebas de JUnit en mis métodos de servicio, y después de cada prueba, me gustaría que los datos escritos en la base de datos en memoria sean revertidos. Sin embargo, NO quiero que toda la prueba se trate como una transacción. Por ejemplo en esta prueba.

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:test-context.xml" }) public class ContractServiceTest { … @Autowired private ContractService m_contractService; @Test public void testUpdateContract() { // Add the contract m_contractService.save(m_contract); Assert.assertNotNull(m_contract.getId()); // Update the activation date by 6 months. final Calendar activationDate = Calendar.getInstance(); activationDate.setTime(activationDate.getTime()); activationDate.add(Calendar.MONTH, 6); m_contract.setActivationDate(activationDate.getTime()); m_contractService.save(m_contract); final List<Contract> foundContracts = m_contractService.findContractByOppId(m_contract.getOpportunityId()); Assert.assertEquals(foundContracts.get(0), m_contract); } // testUpdateContract

hay tres llamadas al servicio, ("m_contractService.save", "m_contractService.save" y "m_contractService.findContractByOppId") y cada una se trata como una transacción, lo que quiero. Pero no sé cómo restablecer mi base de datos en memoria a su estado original después de cada prueba de unidad.

Avísame si necesito proporcionar información adicional.


Cree un método @Before en el que elimine todos los datos de la base de datos. Está utilizando Hibernate por lo que puede usar HQL: delete from Contract .


Puede usar la anotación @Transactional en el nivel de clase Junit desde org.springframework.transaction.annotation.Transactional .

Por ejemplo:

package org.test import org.springframework.transaction.annotation.Transactional; @Transactional public class ArmyTest{ }


Ya que está utilizando hibernación, puede usar la propiedad hibernate.hbm2ddl.auto para crear la base de datos en el inicio cada vez. También deberá forzar que el contexto del resorte se vuelva a cargar después de cada prueba. Puedes hacer esto con la anotación @DirtiesContext.

Esto podría agregar un poco más de sobrecarga a sus pruebas, por lo que la otra solución es simplemente eliminar manualmente los datos de cada tabla.