2012-05-14 8 views
9

Esencia:JBehave con SpringJUnit4ClassRunner para permitir la reversión de transacciones

¿Cómo puedo de auto-retroceso mi transacción de hibernación en una prueba JUnit con JBehave?

El problema parece ser que JBehave quiere el SpringAnnotatedEmbedderRunner pero anotar una prueba como @Transactional requiere el SpringJUnit4ClassRunner.

He intentado encontrar alguna documentación sobre cómo implementar reversión con SpringAnnotatedEmbedderRunner o hacer que JBehave funcione usando el SpringJUnit4ClassRunner pero no pude ni trabajar.

¿Alguien tiene una configuración (preferiblemente simple) que ejecuta JBehave Storries con Spring e Hibernate y retrotracción automática de transacciones?



más info sobre mi configuración hasta ahora:

JBehave de Trabajo con la primavera - pero no con auto-rollback:

@RunWith(SpringAnnotatedEmbedderRunner.class) 
@Configure(parameterConverters = ParameterConverters.EnumConverter.class) 
@UsingEmbedder(embedder = Embedder.class, generateViewAfterStories = true, ignoreFailureInStories = false, ignoreFailureInView = false) 
@UsingSpring(resources = { "file:src/main/webapp/WEB-INF/test-context.xml" }) 
@UsingSteps 
@Transactional // << won't work 
@TransactionConfiguration(...) // << won't work 
// both require the SpringJUnit4ClassRunner 

public class DwStoryTests extends JUnitStories { 

    protected List<String> storyPaths() { 

     String searchInDirectory = CodeLocations.codeLocationFromPath("src/test/resources").getFile(); 
     return new StoryFinder().findPaths(searchInDirectory, Arrays.asList("**/*.story"), null); 
    } 

} 

En mis pasos de prueba que pueda @Inject todo muy bien:

@Component 
@Transactional // << won't work 
public class PersonServiceSteps extends AbstractSmockServerTest { 

    @Inject 
    private DatabaseSetupHelper databaseSetupHelper; 

    @Inject 
    private PersonProvider personProvider; 

    @Given("a database in default state") 
    public void setupDatabase() throws SecurityException { 
     databaseSetupHelper.createTypes(); 
     databaseSetupHelper.createPermission(); 
    } 

    @When("the service $service is called with message $message") 
    public void callServiceWithMessage(String service, String message) { 
     sendRequestTo("/personService", withMessage("requestPersonSave.xml")).andExpect(noFault()); 
    } 

    @Then("there should be a new person in the database") 
    public void assertNewPersonInDatabase() { 
     Assert.assertEquals("Service did not save person: ", personProvider.count(), 1); 
    } 

(sí, los métodos databaseSetupHelper son todos transaccional)

PersonProvider es básicamente una envoltura alrededor de org.springframework.data.jpa.repository.support.SimpleJpaRepository. Entonces, hay acceso al entityManager, pero tomar el control de las transacciones (con inicio/retroceso) no funcionó, supongo que debido a todos los @Transactional s que se realizan bajo el capó dentro de esa clase de ayuda.

También he leído que JBehave se ejecuta en un contexto diferente? Sesión? Algo? que causa la pérdida de control sobre la transacción iniciada por la prueba? Algo bastante confuso ..


edición:

Editet lo anterior reformular el post para reflejar mi conocimiento actual y acortar todo el asunto por lo que la cuestión se hace más evidente y la configuración de menos demasiado prominente.

Respuesta

2

Creo que puede omitir SpringAnntedtedEmbedderRunner y proporcionar la configuración necesaria para JBehave usted mismo.Por ejemplo en lugar de

@UsingEmbedder(embedder = Embedder.class, generateViewAfterStories = true, ignoreFailureInStories = false, ignoreFailureInView = false) 

que puede hacer

configuredEmbedder() 
.embedderControls() 
.doGenerateViewAfterStories(true) 
.doIgnoreFailureInStories(false) 
.doIgnoreFailureInView(false); 

Además: ¿por qué quiere deshacer la transacción? Normalmente está utilizando JBehave para las pruebas de aceptación, que se ejecutan en un entorno de producción similar. Por ejemplo, primero configura algunos datos en la base de datos, accede a ellos a través de Browser/Selenium y verifica los resultados. Para que eso funcione, la transacción DB debe ser comprometida. Necesita realizar una limpieza manual después de las pruebas, lo que puede hacer en los métodos anotados @AfterStories o @AfterScenario.

+0

Hm .. Suena como algo que podría intentar. Gracias, lo verificaremos la próxima semana. Nuestras pruebas de aceptación no se ejecutarán contra la aplicación implementada, sino que la reservamos para las pruebas de extremo a extremo. Nuestras pruebas de aceptación se ejecutarán contra el modelo de dominio directamente, incluida una base de datos limpia que queremos autorrutar. – Pete

1

No estoy familiarizado con JBehave, pero parece que estás buscando esta anotación.

@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true). 

También podría establecer defaultRollback en true en su testContext.

+0

No, eso no funcionará. Es una anotación 'SpringJUnit4ClassRunner' que será ignorada por' SpringAnnotedEDBedderRunner' de JBehave. – Pete

1

Lo hice funcionar controlando el alcance de la transacción de forma manual, retrotrándolo después de cada escenario. Simplemente sigue la guía oficial de cómo usar Spring con JBehave y luego haz el truco como se muestra a continuación.

@Component 
public class MySteps 
{ 
    @Autowired 
    MyDao myDao; 

    @Autowired 
    PlatformTransactionManager transactionManager; 

    TransactionStatus transaction; 

    @BeforeScenario 
    public void beforeScenario() { 
     transaction = transactionManager.getTransaction(new DefaultTransactionDefinition()); 
    } 

    @AfterScenario 
    public void afterScenario() { 
     if (transaction != null) 
      transactionManager.rollback(transaction); 
    } 

    @Given("...") 
    public void persistSomething() { 
     myDao.persist(new Foo()); 
    } 
} 
Cuestiones relacionadas