2012-05-14 13 views
9

Essence:Łącząc JBehave z SpringJUnit4ClassRunner włączyć cofnąć transakcji

Jak mogę auto stoczeniu mój transakcja hibernacji w próbnym uruchomieniu JUnit z JBehave?

Problem polega na tym, że JBehave chce mieć SpringAnnotatedEmbedderRunner, ale przypisanie testu jako @Transactional wymaga SpringJUnit4ClassRunner.

Próbowałem znaleźć dokumentację, jak wdrożyć wycofanie z SpringAnnotatedEmbedderRunner lub aby JBehave działało przy użyciu SpringJUnit4ClassRunner, ale nie mogłem uzyskać ani działać.

Czy ktoś ma (najlepiej prostą) konfigurację, która obsługuje magazyny JBehave z funkcją Spring and Hibernate i automatycznym wycofywaniem transakcji?



Dalsze informacje o mojej konfiguracji tej pory:

JBehave Działa z wiosny - ale nie z automatycznego wycofywania:

@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); 
    } 

} 

W moich kroków testowych mogę @Inject wszystko ładnie:

@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); 
    } 

(tak, metody databaseSetupHelper są transakcyjny)

PersonProvider jest w zasadzie owinięcie wokół org.springframework.data.jpa.repository.support.SimpleJpaRepository. Tak więc istnieje dostęp do entityManager, ale przejęcie kontroli nad transakcjami (z rozpoczęciem/wycofaniem) nie działało, myślę, że ze względu na wszystkie @Transactional s, które są wykonywane pod maską wewnątrz tej klasy pomocnika.

Czytałem również, że JBehave działa w innym kontekście? Sesja? Coś? co powoduje utratę kontroli nad transakcją rozpoczętą przez test? Dość skomplikowane rzeczy ..


edit:

Editet wyżej przeformułowanie stanowisko do zastanowienia mój aktualny stan wiedzy i skraca całą sprawę tak, że kwestia staje się coraz bardziej oczywiste i konfiguracja mniej obstrusive.

Odpowiedz

2

Myślę, że możesz pominąć SpringAnnotatedEmbedderRunner i dostarczyć niezbędną konfigurację JBehave.Na przykład zamiast

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

można zrobić

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

Poza tym: dlaczego chcesz wycofać transakcję? Zazwyczaj używasz JBehave do testów akceptacyjnych, które działają w środowisku podobnym do produkcji. Na przykład najpierw skonfigurowałeś niektóre dane w bazie danych, uzyskasz dostęp do nich przez przeglądarkę/selen i sprawdzasz wyniki. Aby to działało, transakcja DB musi zostać zatwierdzona. Czy chcesz oczyścić ręcznie po swoich testach, co można zrobić w metodach opatrzonych komentarzem @AfterStories lub @AfterScenario.

+0

Hm .. Brzmi jak coś, co mógłbym spróbować. Dzięki, sprawdzi to w przyszłym tygodniu. Nasze testy akceptacyjne nie będą działać przeciwko wdrożonej aplikacji, zastrzegamy, że w przypadku testów end-to-end. Nasze testy akceptacyjne będą opierać się bezpośrednio na modelu domeny, w tym na czystej bazie danych, którą chcemy automatycznie odzyskać. – Pete

1

Nie znam JBehave, ale wygląda na to, że szukasz tej adnotacji.

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

Można również ustawić wartość defaultRollback na true w swoim tekście testowym.

+0

Nie, to nie zadziała. Jest to adnotacja 'SpringJUnit4ClassRunner', która zostanie zignorowana przez' SpringAnnotatedEmbedderRunner' JBehave'a. – Pete

1

Zrobiłem to, kontrolując zakres transakcji ręcznie, wycofując go po każdym scenariuszu. Wystarczy postępować zgodnie z oficjalnym przewodnikiem, jak korzystać ze Springa przy pomocy JBehave, a następnie wykonać sztuczkę, jak pokazano poniżej.

@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()); 
    } 
} 
Powiązane problemy