예외 발생시 롤백 테스트
스프링 부트에서 오류가 발생했을때 트랜잭션이 롤백되는걸 확인한다.
롤백 테스트
Section titled “롤백 테스트”- 테스트 절차
- 백앤드 애플리케이션에서 데이터를 생성한다.
- try 구문에서 익셉션을 던져서 catch 구문에서 잡히도록 한다.
- 1단계에서 생성한 데이터가 롤백되었는지 확인한다.
SpringBootService.kt fun testRollback(param: PhotoBoard) {try {photoBoardMapper.insertPhotoBoard(param)throw RuntimeException("test")} catch (e: Exception) {throw BizException(e)}}SpringBootService.java public void testRollback(final PhotoBoard param) {try {photoBoardService.insertPhotoBoard(param);throw new RuntimeException("test");} catch (final Exception e) {throw new BizException(e);}}- 컨트롤러 코드
SpringBootController.kt @Operation(summary = "예외 발생시 데이터가 롤백되는것을 확인하기 위한 테스트", description = "예외 발생시 데이터가 롤백되는것을 확인하기 위한 테스트 API")@PostMapping("/rollback-test")fun testRollback(@Valid @ModelAttribute param: InsertPhotoBoardRequest): ResponseEntity<ResponseDto<Unit>> {log.info("testRollback param: $param")val model = param.toModel()springBootService.testRollback(model)return ResponseEntity.status(HttpStatus.CREATED).body((ResponseDto(Unit)))}SpringBootController.java @Operation(summary = "예외 발생시 데이터가 롤백되는것을 확인하기 위한 테스트", description = "예외 발생시 데이터가 롤백되는것을 확인하기 위한 테스트 API")@PostMapping(path = "/rollback-test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)public ResponseEntity<Void> testRollback(@Valid @ModelAttribute InsertPhotoBoardRequest param) {log.info("param: {}", param);springBootService.testRollback(param.toModel());return ResponseEntity.status(HttpStatus.OK).build();} - 테스트 실행
IntegrationSpringBootTest.kt @DisplayName("예외 발생시 데이터가 롤백되는것을 확인하기 위한 테스트")@Testfun `예외 발생시 데이터가 롤백되는것을 확인하기 위한 테스트`() {return Given {spec(multipartRequestSpecification)formParam("title", "test")formParam("content", "test")multiPart("photo", "sample2.jpg", readResourceFileAsBytes("sample/image/sample2.jpg"), MediaType.IMAGE_JPEG_VALUE)} When {post("/spring-boot/rollback-test")} Then {statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR)} Extract {println(body().asString())}}IntegrationSpringBootTest.java @DisplayName("예외 발생시 데이터가 롤백되는것을 확인하기 위한 테스트")@Testvoid testRollback() {given().spec(multipartRequestSpecification).formParam("title", "test").formParam("content", "test").multiPart("photo", "sample2.jpg", FileUtil.readClasspathFile("sample/image/sample2.jpg"), MediaType.IMAGE_JPEG_VALUE).when().post("/spring-boot/rollback-test").then().statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR).log().all();} - 로그 확인
- 데이터 생성
2026-02-10 15:13:44,732 [DEBUG] [http-nio-auto-1-exec-1] n.s.l.l.s.Slf4jSpyLogDelegator: com.zaxxer.hikari.pool.ProxyStatement.getGeneratedKeys(ProxyStatement.java:230)1. getGeneratedKeys on query: /*insertPhotoBoard*/INSERT INTO T_PHOTO_BOARD ( TITLE, CONTENT, PHOTO_PATH, CREATE_DT, CREATE_USER_ID, CREATE_IP, UPDATE_DT, UPDATE_USER_ID, UPDATE_IP )VALUES ( 'test', 'test', 'http://localhost/photo/sample2.jpg', NOW(), 1000, '0:0:0:0:0:0:0:1', NOW(), 1000, '0:0:0:0:0:0:0:1' ){executed in 1 msec}2026-02-10 15:13:44,738 [INFO ] [http-nio-auto-1-exec-1] n.s.l.l.s.Slf4jSpyLogDelegator:|--------------||generated_key ||--------------||1048 ||--------------|2026-02-13 11:00:39,069 [DEBUG] [http-nio-auto-1-exec-2] n.s.l.l.s.Slf4jSpyLogDelegator: com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)1. /*insertPhotoBoard*/INSERT INTO PHOTO_BOARD ( TITLE, CONTENT, PHOTO_PATH, CREATE_DT, CREATE_USER_ID, CREATE_IP, UPDATE_DT, UPDATE_USER_ID, UPDATE_IP )VALUES ( 'test', 'test', 'http://localhost:8080/sample2.jpg', NOW(), -1, '127.0.0.1', NOW(), -1, '127.0.0.1' ){executed in 7 msec}2026-02-13 11:00:39,071 [DEBUG] [http-nio-auto-1-exec-2] o.a.i.l.j.BaseJdbcLogger: <== Updates: 12026-02-13 11:00:39,072 [DEBUG] [http-nio-auto-1-exec-2] n.s.l.l.s.Slf4jSpyLogDelegator: com.zaxxer.hikari.pool.ProxyStatement.getGeneratedKeys(ProxyStatement.java:229)1. getGeneratedKeys on query: /*insertPhotoBoard*/INSERT INTO PHOTO_BOARD ( TITLE, CONTENT, PHOTO_PATH, CREATE_DT, CREATE_USER_ID, CREATE_IP, UPDATE_DT, UPDATE_USER_ID, UPDATE_IP )VALUES ( 'test', 'test', 'http://localhost:8080/sample2.jpg', NOW(), -1, '127.0.0.1', NOW(), -1, '127.0.0.1' ){executed in 0 msec}2026-02-13 11:00:39,078 [INFO ] [http-nio-auto-1-exec-2] n.s.l.l.s.Slf4jSpyLogDelegator:|--------------||generated_key ||--------------||1051 ||--------------|
- 익셉션 발생후 롤백된걸 확인
2026-02-10 15:13:44,793 [ERROR] [http-nio-auto-1-exec-1] b.m.c.c.e.a.RestApiExceptionAdvice: ### BizException occurredjava.lang.RuntimeException: test...{"payload":null,"isSuccess":false,"resultCode":"FAILURE","message":"test"}[2026-02-10 15:23:18] carrot> select * from T_PHOTO_BOARD where PHOTO_BOARD_ID = 1048[2026-02-10 15:23:18] 372 ms (execution: 20 ms, fetching: 352 ms)에서 0개 행 불러옴2026-02-13 11:00:39,114 [ERROR] [http-nio-auto-1-exec-2] c.e.s.c.e.a.RestApiExceptionAdvice: ### BizException Occurred. ID: [960155]java.lang.RuntimeException: test...2026-02-13 11:00:39,186 [INFO ] [http-nio-auto-1-exec-2] c.e.s.c.u.LogGenerator: ID: [960155] Response Status: [500] duration: [304] Body: [{"payload":null,"successYn":"N","messageCd":"test"}]HTTP/1.1 500Vary: OriginVary: Access-Control-Request-MethodVary: Access-Control-Request-HeadersX-Request-ID: 960155X-Content-Type-Options: nosniffX-XSS-Protection: 0Cache-Control: no-cache, no-store, max-age=0, must-revalidatePragma: no-cacheExpires: 0X-Frame-Options: DENYSet-Cookie: JSESSIONID=ZDIxODQ0ZjgtZjIyMi00MWM4LTk5NjEtNTkxOTkyMTYxZDA4; Path=/; HttpOnly; SameSite=LaxContent-Type: application/jsonTransfer-Encoding: chunkedDate: Fri, 13 Feb 2026 02:00:39 GMTConnection: close{"payload": null,"successYn": "N","messageCd": "test"}[2026-02-13 11:17:00] si_helper> select * from PHOTO_BOARD where PHOTO_BOARD_ID = 1051[2026-02-13 11:17:00] 463 ms (execution: 18 ms, fetching: 445 ms)에서 0개 행 불러옴
- 데이터 생성