[SPRING] @ TransactionalEvents 및 @Rollback 테스트
SPRING@ TransactionalEvents 및 @Rollback 테스트
나는 @TransactionalEvents (Spring 4.2의 기능인 https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2)를 테스트하려고 노력 해왔다. 기존의 Spring JUnit 테스트 (@TransactionalTestExecutionListener를 통해 실행되거나 AbstractTransactionalUnit4SpringContextTests를 서브 클래 싱하는 것이지만, @Rollback 주석없이 테스트를 실행하거나 이벤트가 실행되지 않는 것처럼 보입니다.) @Rollback 테스트를 수행하면서 @TransactionalEvents를 테스트 하시겠습니까?
해결법
-
==============================
1.Stéphane Nicoll은 맞습니다. @TransactionalEventListener의 TransactionPhase가 AFTER_COMMIT로 설정된 경우 자동 롤백 의미론을 사용하여 트랜잭션 테스트를 수행하는 것은 이벤트가 절대로 실행되지 않으므로 의미가 없습니다.
Stéphane Nicoll은 맞습니다. @TransactionalEventListener의 TransactionPhase가 AFTER_COMMIT로 설정된 경우 자동 롤백 의미론을 사용하여 트랜잭션 테스트를 수행하는 것은 이벤트가 절대로 실행되지 않으므로 의미가 없습니다.
즉, 트랜잭션이 커밋되지 않은 경우 트랜잭션이 커밋 된 후 이벤트가 시작되는 방법이 없습니다.
따라서 이벤트를 실행하려면 트랜잭션을 커밋해야합니다 (예 : 테스트 메소드에 @Commit 주석을 달아서). 커밋 후에 정리하려면 격리 모드에서 @Sql을 사용하여 트랜잭션이 커밋 된 후 정리 스크립트를 실행할 수 있어야합니다. 예를 들어, 다음과 같은 (테스트되지 않은 코드)가 작동 할 수 있습니다.
@Transactional @Commit @Sql(scripts = "/cleanup.sql", executionPhase = AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = TransactionMode.ISOLATED)) @Test public void test() { /* ... */ }
문안 인사,
Sam (Spring TestContext Framework 작성자)
-
==============================
2.Sam Brannen의 해결책은 adam의 의견과 관련하여 거의 작동합니다.
Sam Brannen의 해결책은 adam의 의견과 관련하여 거의 작동합니다.
사실, @TransactionalEventListener로 주석 된 메소드는 테스트 메소드 트랜잭션이 커밋 된 후에 호출됩니다. 이는 이벤트를 발생시키는 호출 메소드가 실제 트랜잭션이 아닌 논리적 트랜잭션 내에서 실행되기 때문입니다.
대신, 호출 메소드가 새로운 물리적 트랜잭션 내에서 실행될 때, @TransactionalEventListener로 주석 처리 된 메소드는 적시에, 즉 테스트 메소드 트랜잭션이 커밋되기 전에 호출됩니다.
또한 우리는 실제로 이러한 트랜잭션에 관심이 없기 때문에 테스트 메소드에 @Commit이 필요하지 않습니다. 그러나 Sam Brannen이 설명하는 @Sql (...) 문이 호출 된 메서드의 커밋 된 변경 내용을 취소하려면 필요합니다.
아래의 작은 예를 참조하십시오.
먼저 트랜잭션이 커밋 될 때 호출되는 리스너 (@TransactionalEventListener의 기본 비헤이비어)
@Component public class MyListener { @TransactionalEventListener public void when(MyEvent event) { ... } }
그런 다음 위의 클래스에서 청취 한 이벤트를 게시하는 애플리케이션 서비스. 메소드가 호출 될 때마다 트랜잭션이 새로운 물리적 인 트랜잭션이되도록 구성되어 있습니다 (자세한 내용은 Spring Framework 문서를 참조하십시오) :
@Service @Transactional(propagation = Propagation.REQUIRES_NEW) public class MyApplicationService { public void doSomething() { // ... // publishes an instance of MyEvent // ... } }
마지막으로 Sam Brannen이 제안한 테스트 방법으로 @Commitannotation은 필요하지 않습니다.
@Transactional @Sql(scripts = "/cleanup.sql", executionPhase = AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = TransactionMode.ISOLATED)) @Test public void test() { MyApplicationService target = // ... target.doSomething(); // the event is now received by MyListener // assertions on the side effects of MyListener // ... }
이렇게하면 매력처럼 작동합니다 :-)
from https://stackoverflow.com/questions/36536466/testing-transactionalevents-and-rollback by cc-by-sa and MIT license