Java/스프링 Reactive
[R2dbc] R2dbc Test시 Rollback이 되지 않음.
요깨비
2021. 5. 25. 15:59
개인 프로젝트를 진행하던 도중, Test 후 Rollback이 되어야 할 기능이 정상 작동하지 않아 이를 해결한 과정을 적습니다.
해당 방법은 완전한 정답은 아니고, R2dbc를 담당하는 외국 개발자들이 적은 내용들을 참고하여 작성하였습니다.
@SpringBootTest
@Transactional
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores::class)
class OrderRepositoryTest @Autowired constructor(
private val orderRepository: OrderRepository
) {
val log = Slf4JLoggerFactory.getInstance(OrderRepositoryTest::class.java)
@Test
@DisplayName("[OrderRepository] 주문 생성 테스트")
fun createOrderTest() {
val order = Order(
"create-order-test",
"product-01",
"sender1",
...
)
order.setAsNew()
log.info("[OrderRepository] 주문 생성 테스트")
StepVerifier.create(orderRepository.save(order))
.expectSubscription()
.consumeNextWith {
Assertions.assertEquals("create-order-test", it.orderId)
log.info("$it")
log.info("END")
}
.verifyComplete()
}
}
주문 생성을 테스트 하던 중 생성 데이터가 롤백이 되지 않았습니다. Stackoverflow를 참조하여 여러 방법들을 적용하였으나,
Rollback이 똑같이 안되거나, Exception이 발생하는 등 적절한 해답이 되지 못했습니다. 그러던 도중
공식 스프링 Git 사이트에 비슷한 문제를 제기한 ISSUE가 있었습니다.
공식적인 대답은
2019년 12월 기준 아직 공식적으로 지원하지 않는 것 같습니다. 또한, 2020년 8월 기준 다른 개발자가 해결 방법이 제시하여
해당 방법으로 문제를 해결하였습니다.
위 Transaction 코드를 이용하여 해당 객체가 담당하는 책임을 Stepverifier 혹은 Reactive 코드에 적용하여 해당 기능이 끝날 때 Rollback을 수행하도록 하였습니다.
@SpringBootTest
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores::class)
class OrderRepositoryTest @Autowired constructor(
private val orderRepository: OrderRepository
) {
val log = Slf4JLoggerFactory.getInstance(OrderRepositoryTest::class.java)
@Test
@DisplayName("[OrderRepository] 주문 생성 테스트")
fun createOrderTest() {
val order = Order(
"create-order-test",
"product-01",
"sender1",
...
)
order.setAsNew()
log.info("[OrderRepository] 주문 생성 테스트")
orderRepository.save(order)
.map(Order::orderId)
.flatMap(orderRepository::findById)
.`as`(Transaction::withRollback)
.`as`(StepVerifier::create)
.assertNext { order ->
Assertions.assertEquals(true, order!!.orderId == "create-order-test")
}
.verifyComplete()
}
}
테스트 관련해서 Rollback이 잘 작동하는 것을 확인하였습니다.
해당 방식의 문제점이나 더 나은 개선점이 있으시다면 알려주시면 정말 감사드리겠습니다.
https://github.com/spring-projects/spring-framework/issues/24226