@Test 후 트랜잭션 롤백


85

우선, 이것에 대해 StackOverflow에서 많은 스레드를 찾았지만 그들 중 누구도 나를 도와주지 않았기 때문에 중복 질문을해서 죄송합니다.

스프링 테스트를 사용하여 JUnit 테스트를 실행 중입니다. 내 코드는 다음과 같습니다.

@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() {
    }    
    ...  
}

내 문제는 내 테스트가 다른 테스트에 영향을 미치지 않기를 원한다는 것입니다. 그래서 각 테스트에 대해 롤백과 같은 것을 만들고 싶습니다. 나는 이것을 많이 검색했지만 지금까지 아무것도 찾지 못했습니다. 나는 이것을 위해 Hibernate와 MySql을 사용하고 있습니다.


롤백이란 무엇을 의미합니까?. 데이터베이스를 정리 하시겠습니까?
Gaurav

5
실행 후와 똑같은 상태로 설정initTest
Jan

답변:


127

@Transactional테스트 위에 주석을 추가하기 만하면됩니다 .

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

기본적으로 Spring은 테스트 메서드 및 @Before/ @After콜백을 둘러싼 새 트랜잭션을 시작 하고 끝에서 롤백합니다. 기본적으로 작동하며 컨텍스트에 트랜잭션 관리자가 있으면 충분합니다.

From : 10.3.5.4 트랜잭션 관리 (굵은 광산) :

TestContext 프레임 워크에서 트랜잭션은 TransactionalTestExecutionListener에 의해 관리됩니다. 참고 TransactionalTestExecutionListener된다 기본적으로 구성 명시 적으로 선언하지 않는 경우에도, @TestExecutionListeners테스트 클래스. 그러나 트랜잭션에 대한 지원을 사용하려면 시맨틱에 PlatformTransactionManager의해로드 된 애플리케이션 컨텍스트에 Bean을 제공해야합니다 @ContextConfiguration. 또한 테스트를 위해 클래스 또는 메서드 수준에서 선언해야합니다@Transactional .


2
글쎄, 나는 이것을 전에 시도했지만 여전히 작동하지 않습니다. 아마도 ... 문제는 내가 PlatformTransactionManager를 정의하지 않았기 때문에 어떻게 할 수 있습니까?
Jan Vorcak

@javo : 데이터베이스를 어떻게 수정하고 있습니까? Jpa / Hibernate / JdbcTemplate / ...을 사용한다면 PlatformTransactionManager. 그렇지 않으면 Spring이 트랜잭션과 데이터베이스에 대해 어떻게 알 수 있습니까?
Tomasz Nurkiewicz

1
이 답변의 링크는 더 이상 올바르지 않습니다. Spring 문서의 올바른 링크와 더 많은 컨텍스트는 아래 user2418306의 답변을 참조하십시오 .
DaveyDaveDave

1
나는 전체 클래스에 그것을 할 캔트, 각 방법은 별도의 트랜잭션을 필요로 작동하지 않습니다
카밀 Nekanowicz에게

테이블에 삽입을 테스트하고 있습니다. @Transactional을 사용하면 데이터베이스에 대해 insert 명령이 실행되지도 않습니다 (콘솔에 최대 절전 모드 show-sql true가 있기 때문에 알 수 있습니다). 많은 경우에 잘 작동합니다. 그러나 내 테스트 중 하나는 데이터베이스 제약 조건으로 인해 데이터베이스가 DataAccessException을 발행하는지 확인합니다. 이 경우 롤백이 "메모리에서"발생하고 데이터베이스가 호출되지 않기 때문에 테스트가 실패합니다. 해결 방법 : @Transactional상기 @Test방법 수준이 아닌 클래스 수준.
Paulo Merson

17

곁에 : Tomasz Nurkiewicz의 대답을 수정하려는 시도는 거부되었습니다.

이 편집은 게시물을 좀 더 읽기 쉽고, 찾기 쉽고, 더 정확하거나, 더 쉽게 접근 할 수 있도록하지 않습니다. 변경 사항은 완전히 불필요하거나 가독성에 적극적으로 영향을 미칩니다.


통합 테스트에 대한 문서의 관련 섹션에 대한 정확하고 영구적 인 링크 .

트랜잭션 지원을 사용하려면 시맨틱을 통해로드되는 PlatformTransactionManager에서 Bean을 구성해야합니다 .ApplicationContext@ContextConfiguration

@ 구성
@PropertySource ( "application.properties")
public class Persistence {
    @Autowired
    환경 env;

    @콩
    DataSource dataSource () {
        새로운 DriverManagerDataSource (
                env.getProperty ( "datasource.url"),
                env.getProperty ( "datasource.user"),
                env.getProperty ( "datasource.password")
        );
    }

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

또한 @Transactional테스트를 위해 클래스 또는 메서드 수준에서 Spring의 주석을 선언해야합니다 .

@RunWith (SpringJUnit4ClassRunner.class)
@ContextConfiguration (classes = {Persistence.class, SomeRepository.class})
@ 거래
공용 클래스 SomeRepositoryTest {...}

테스트 메서드에 주석을 추가 @Transactional하면 기본적으로 테스트 완료 후 자동으로 롤백되는 트랜잭션 내에서 테스트가 실행됩니다. 테스트 클래스에로 주석이 달린 경우 @Transactional해당 클래스 계층 구조 내의 각 테스트 메서드는 트랜잭션 내에서 실행됩니다.


12

추가에 대한 답변 @Transactional은 정확하지만 간단하게 테스트 클래스를 가질 수 있습니다 extends AbstractTransactionalJUnit4SpringContextTests.


1
클래스 수준의 '@Transactional'주석을 추가하면 각 기능의 작동에 대해 개별적으로하지 작업, 추가 주석 '@Transactional'하지, 너무 AbstractTransactionalJUnit4SpringContextTests을 작품 확장
카밀 Nekanowicz

5

나는 답변을 게시하기에는 너무 늦었지만 누군가에게 도움이되기를 바랍니다. 또한 테스트를 통해이 문제를 해결했습니다. 이것은 내 테스트에서 얻은 것입니다.

내 시험 수업

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

컨텍스트 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>

데이터베이스가 자동으로 정리되지 않는다는 문제가 여전히 발생했습니다.

BasicDataSource에 다음 속성을 추가하면 문제가 해결되었습니다.

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

도움이되기를 바랍니다.


글쎄, 당신은 당신의 진술을 수동으로 커밋합니까? 데이터가 데이터베이스에 기록 되었습니까?
franta kocourek

Spring Transactions를 이해하는 데 어려움을 겪는 사람을 위해 데이터 소스가 자동 커밋으로 설정되어 있지 않은지 확인하십시오.
Joe Ernst

2

Spring 컨텍스트와 트랜잭션 관리자로 테스트를 실행해야합니다. 예 :

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

자세한 내용 3.5.8. Transaction Management은 Spring 참조 장 을 참조하십시오.


0

방법 을 추가 @Transactional하는 것 외에도 추가 @Test해야합니다.@Rollback(false)


-4

롤백을 비활성화 할 수 있습니다.

@TransactionConfiguration(defaultRollback = false)

예:

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

6
즉 정확히 OP가 요구되는 것을 반대입니다
아담 미칼

이것은 받아 들여진 답변에 대한 의견이어야합니다.
DerMike
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.