[java] @Test 후 트랜잭션 롤백

우선, 이것에 대해 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을 사용하고 있습니다.



답변

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


답변

곁에 : 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해당 클래스 계층 구조 내의 각 테스트 메서드는 트랜잭션 내에서 실행됩니다.


답변

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


답변

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

내 시험 수업

@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" />

도움이되기를 바랍니다.


답변

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 참조 장 을 참조하십시오.


답변

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


답변

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

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