POST /artist/{artist-id}/comments 로 동작하는 댓글 등록 기능이 DEV환경에 반영 되었음에, 테스트 진행도중 정상동작하지 않는 것을 확인했다. 에러 로그의 전문은 아래와 같다.
Connection is read-only. Queries leading to data modification are not allowed 이라는 로그에 주목해보면, Read-only 커넥션이 맺어져 있기 때문에 쿼리에 의한 데이터 변경이 허용되지 않는다 한다.
가장 먼저 짐작가는 사유는 Service 레이어에서 @Transactional 메소드의 부재였다.
클래스에서 @Transactional(readOnly=true) 로 관리하며, CREATE/UPDATE/DELETE 동작이 수행되는 메소드에 @Transactional 어노테이션을 붙여주며 READ 행위가 발생하는 메소드에서는 어노테이션을 생략하는 것을 팀내 정책으로 가져갔다. 그 이유는 성능 향상(참고 링크) 그리고 Service Layer에서 CRUD중 어떤 동작을 수행하는지 미리보기 형태로 확인할 수 있다라 생각했다.
그런데 ! 서비스 레이어의 테스트 코드가 아래와 같이 기존에 작성 되어있었고, 댓글 등록이 정상 처리가 되지 않았다면 실패했어야 했음에도 테스트 코드는 PASS 처리 되었다.
@DisplayName("아티스트 페이지에서 방문록을 작성할 수 있다.")
@Test
void createComment() {
// given
ConnectableUserDetails connectableUserDetails =
new ConnectableUserDetails(userKlaytnAddress);
ArtistCommentRequest artistCommentRequest =
new ArtistCommentRequest("나는 내 갈길을 간다...! @_@ by mrlee7.");
// when
artistService.createComment(connectableUserDetails, artist1.getId(), artistCommentRequest);
List<Comment> comments = commentRepository.findAll();
// then
assertThat(comments).isNotNull();
assertThat(comments.get(0).getContents()).isEqualTo(artistCommentRequest.getContents());
}
테스트를 구동하는 Local, 빌드가 실행되는 Jenkins CI 모두 h2 database를 사용하고 DEV/PROD는 MySQL로 구성되어있다.
org.springframework.jdbc.datasource.DataSourceTransactionManager의 setEnforceReadOnly를 보면 다음과 같이 작성되어있다.
"SET TRANSACTION READ ONLY" as understood by Oracle, MySQL, Postgres
H2에서는 SET TRANSACTION READ ONLY 가 받아들여지지 않는다는 것인데,,
테스트 환경에서는 read-only가 강제되지 않기에, insert 쿼리가 발생해도 큰 문제가 되지 않았던 것을 DEV/PROD 에서는 MySQL이기에 예외가 발생한것이다. 크게 생각나는 방법으로는 Test Container를 이용해서 로컬환경에서도 WAS가 뜰 때마다 MySQL을 실행시켜주는 것인데, 관련하여 이어서 작성해야겠다.
'DB' 카테고리의 다른 글
Partitioning 여부가 INSERT 쿼리 실행에 미치는 영향 (1) | 2023.09.09 |
---|