2013-02-05 11 views
26

Używam Spring 3.1.1.RELEASE, JUnit 4.8.1 i bazy danych HSBS 2.7.7 w pamięci. Mam jedna klasa Test odnotowany jakoJak zresetować kontekst aplikacji Spring JUnit po zabrudzeniu klasy testowej?

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({ "classpath:test-trainingSessionServiceContext.xml" }) 
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) 
public class TrainingSessionServiceTest 
{ 

jest problem, gdy uruchamiam „mvn czyste testowe”, wydaje się, że wszystkie klasy testy prowadzone po powyższej klasy niepowodzeniem, ponieważ w pamięci bazy danych jest zniszczony i nie ponownie -stworzony. Otrzymuję błędy jak

org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: CB_ORGANIZATION" type="javax.persistence.PersistenceException">javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: CB_ORGANIZATION 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1360) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:817) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:771) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) 
    at $Proxy46.find(Unknown Source) 
    at org.mainco.subco.organization.repo.OrganizationDaoImpl.findById(OrganizationDaoImpl.java:77) 
    at org.mainco.subco.pd.repo.LinkDaoTest.createDummyLink(LinkDaoTest.java:686) 
    at org.mainco.subco.pd.repo.LinkDaoTest.testSaveLink(LinkDaoTest.java:67) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 

Oto jak skonfigurować Klasa testu (uruchom po powyższej klasy), który daje wyjątki ...

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({ "classpath:test-context.xml" }) 
public class LinkDaoTest extends AbstractTransactionalJUnit4SpringContextTests 
{ 

Czy jest jakiś sposób mogę przywrócić moje kontekstu aplikacji do jej oryginalny stan przed uruchomieniem każdej klasy testowej? Nie chcę, aby klasa "TrainingSessionServiceTest" rozszerzała AbstractTransactionalJUnit4SpringContextTests. Oto odpowiednia część kontekstu aplikacji:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> 
    <property name="url" value="jdbc:hsqldb:mem:pd" /> 
    <property name="username" value="sa" /> 
    <property name="password" value="" /> 
</bean> 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> 
    </property> 
    <property name="persistenceXmlLocation" value="classpath:META-INF/test-persistence.xml"/> 
    <property name="persistenceUnitName" value="testingDatabase"/> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

<bean id="sharedEntityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 

<tx:annotation-driven /> 

<jdbc:embedded-database id="embedded" type="HSQL"/> 
<jdbc:initialize-database data-source="dataSource"> 
    <jdbc:script location="classpath:db-test-data.sql"/>  
</jdbc:initialize-database> 
+0

Dla mnie powyższy błąd nie jest związany z kontekstem sprężyny, ale baza danych hsqldb nie jest poprawnie zainicjalizowana: czy Twoja metoda testowa upuszcza bazę danych lub użytkownika? –

+0

Możliwy duplikat [Odśwież kontekst aplikacji Spring po każdym teście] (http://stackoverflow.com/questions/13288029/reload-spring-application-context-after-every-test) – radistao

Odpowiedz

51

Użyj @DirtiesContext, aby wymusić reset. Na przykład, że posiada:

@ContextConfiguration(classes={BlahTestConfig.class}) 
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) 
public class SomeTest { 

    @Autowired XXXX xx; 
    @Autowired YYYY yy; 

    @Before 
    public void setUp() { 
     MockitoAnnotations.initMocks(this); 
     when(YYYY.newYY()).thenReturn(zz); 
    } 

    @Test 
    public void testSomeTest() { 
     XX.changeSomething("StringTest"); 
     XX.doSomething(); 
     check_for_effects(); 
    } 

    @Test 
    public void testSomeOtherTest() { 
     XX.changeSomething("SomeotherString"); 
     XX.doSomething(); 
     check_for_effects(); 
    } 

Z spring docs

DirtiesContext

Wskazuje bazowego Wiosna ApplicationContext została zanieczyszczona (zmodyfikowane) w następujący sposób w trakcie realizacji testu, a powinna być zamknięta niezależnie od tego, czy test minął:

  • Po bieżącej klasie testowej, po zadeklarowaniu dla klasy z klasą , tryb ustawiony na AFTER_CLASS, który jest domyślnym trybem klasy.

  • Po każdej metodzie testu w bieżącej klasie testowej, po zadeklarowaniu na klasie w trybie klasy ustawionym na AFTER_EACH_TEST_METHOD.

  • Po bieżącym teście, po zadeklarowaniu metody.

Użyj tej adnotacji, jeśli test zmodyfikował kontekst (na przykład, zastępując definicję fasoli). Kolejne testy dostarczane są w nowym kontekście. [Uwaga] Ograniczenia @DirtiesContext z JUnit 3,8

> w JUnit 3,8 środowiska @DirtiesContext są obsługiwane tylko w sposobach, a zatem nie na poziomie klasy.

Możesz użyć @DirtiesContext jako adnotacji na poziomie klasy i na poziomie metody w obrębie tej samej klasy. W takich scenariuszach ApplicationContext jest oznaczony jako brudny po każdej takiej opisanej metodzie, a także po całej klasie. Jeśli klasa klasy jest ustawiona na AFTER_EACH_TEST_METHOD, kontekst jest oznaczony jako brudny po każdej metodzie testu w klasie.

@DirtiesContext 
public class ContextDirtyingTests { 
    // some tests that result in the Spring container being dirtied 
} 

@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) 
public class ContextDirtyingTests { 
    // some tests that result in the Spring container being dirtied 
} 

@DirtiesContext 
@Test 
public void testProcessWhichDirtiesAppCtx() { 
    // some logic that results in the Spring container being dirtied 
} 

Gdy kontekst aplikacji jest oznaczony jako zabrudzony, zostaje usunięty z pamięci podręcznej ramek testowych i zamknięty; w ten sposób podstawowy pojemnik Spring zostanie przebudowany na każdy kolejny test wymagający kontekstu z tym samym zbiorem lokalizacji zasobów.

+8

Um ... nie @ Dave's oryginalny kod ** już ** używaj 'DirtiesContext', jak pokazano powyżej. Nie widzę żadnych zmian. czego mi brakuje? – Edmund

+1

W zależności od użycia, może być konieczne dodanie tego ustawienia do wtyczki mvn surefire: false

+0

zapisał mój dzień. Wielkie dzięki! – radistao

Powiązane problemy