본문 바로가기
BackEnd/java

[Mybatis] 테스트 코드 작성

by 하용권 2024. 11. 23.

최근 회사에서 서비스를 분리하고 있습니다.

 

기존 서비스가 점점 거대하지면서 서비스를 분리하려고 했습니다.

서비스를 분리하면서 구현한 기능이 잘 동작하는 지 테스트 해볼 필요가 있습니다.

 

이를 위해서 저는 테스트 코드를 작성하자고 팀원에게 제안했었습니다. 팀원 분도 관심이 있으셔서 받아들였습니다.

(기존에는 테스트 코드가 존재하지 않았었습니다.)

 

 

 

1. 서론

아키텍처 구조는 헥사고날 아키텍처를 이용하고 있습니다.

 

https://github.com/thombergs/buckpal

 

GitHub - thombergs/buckpal: An example approach for implementing a Clean/Hexagonal Architecture

An example approach for implementing a Clean/Hexagonal Architecture - thombergs/buckpal

github.com

이 분의 코드를 보면서 참고했습니다.

 

 

 adapter는 외부와의 통신에 쓰이는 객체들이 존재합니다. 이는 port를 구현을 합니다.

 

예를 들면, 유저 정보를 가져와야 하는 로직이 있을 수 있습니다.

LoadUserAccountPort 로 추상화를 하고, 실제 구현체는 adapter에 구현하는 것 입니다. 이렇게 하는 이유는 DB에서 가져올 수도 있고 추후에 kafka 같은 다른 기술을 이용해서 정보를 가져올 수 있기 때문입니다.

아니면 DB에서 데이터를 가져올 때, JPA나 Mybatis, QueryDSL 등 다양한 기술을 사용할 수 있습니다. 기술이 바뀌더라도 추상화한 부분은 그래도이기 때문에 이러한 구조가 유용합니다.

 

 

out port에는 외부와 통신하는 부분이, in port에는 외부(controller 등)에서 들어오는 요청을 처리하는 use case를 추상화합니다.

out port에서 추상화한 객체는 adapter.out에 구현을 하고, use case는 domain.service에 구현을 합니다.

 

2. 본론

보통 서비스의 경우에는 다양한 out port를 이용해서 로직을 작성하게 됩니다.

out port의 경우에는 mocking을 이용해서 @SpringBootTest 같은 어노테이션 없이 쉽게 코드를 테스트할 수 있었습니다. 

 

이제 adapter를 테스트해야 했습니다. 현재는 mybatis를 이용해서 다양한 정보를 가져오고 있습니다.

그래서 mybatis에 대한 로직도 테스트할 필요가 있지만, 문제가 있었습니다.

 

  1. 테이블 생성 필요

  2. 실제 DB 와 연결 필요

 

이 부분이 문제였습니다.

 

MybatisTest를 검색해보니, 공식사이트에서

https://mybatis.org/spring-boot-starter/mybatis-spring-boot-test-autoconfigure/

 

mybatis-spring-boot-test-autoconfigure – Introduction

Introduction Translations Users can read about MyBatis-Spring-Boot-Starter-Test in the following translations: What is MyBatis-Spring-Boot-Starter-Test? The MyBatis-Spring-Boot-Starter-Test help creating a test cases for MyBatis component using the MyBatis

mybatis.org

mybatis test 관련 글이 있었습니다.

 

그래서 이를 참고해서 코드를 작성해보았습니다.

 

제가 원하는 adapter만 테스트를 하고 싶었기 때문에 Import를 이용했습니다.

다른 로직들이 빈 주입할 때 에러가 생기거나 설정 누락 등 다양한 이유로 실패할 수 있습니다. 이 여파가 제가 테스트 하려는 기능에까지 와서 제 테스트 로직이 실패할 수 있기 때문에 Import를 이용했습니다.

 

또한 @MybatisTest를 이용하면 로컬에 별도의 DB를 띄울 필요가 없습니다.

 

이렇게 작성하면 될 것 같았지만.... 어림도 없었습니다. sql에서 특정 쿼리를 인식하지 못하는 문제가 있었습니다.

mybatis mapper에 postgreSQL에서만 지원하는 기능(TO_TIMESTAMP 등)을 사용하면 문제가 발생합니다.

 

@MybatisTest는 아래의 설정을 이용하기 때문에 문제가 발생했었습니다.

@AutoConfigureTestDatabase

이 설정을 이용해서 자동으로 H2 DB를 이용하게 되다 보니, postgreSQL에서만 지원하는 기능을 이용할 수가 없었습니다.

 

이를 해결하기 위해서 내장 postgreSQL을 지원해주는 지 찾아봤었지만, 저는 못 찾았습니다..

찾다보니 H2의 설정에서

 

이러한 값을 주면 된다고 합니다.

 

그래서 test.resource 패키지에 application.yml 파일을 만들어서 해봤습니다.

이러면 mapper.xml의 위치를 찾지 못하게 됩니다. 그렇다고 이 mapper.xml을 전부 테스트 패키지로 복사해서 들고오자고 하니 관리하기가 힘들 것 같았습니다. 

 

그래서 직접 data source를 직접 커스텀 후, 빈 주입을 하면 될 것이라고 생각했습니다.

@AutoConfigurationTestDatabase에서 None을 이용해서 자동으로 H2로 설정해주는 것을 껐습니다.

 

그리고 @TestConfiguration을 이용해서 직접 설정을 해주었습니다.

(그림상에서는 빨간 줄이 뜹니다. Gradle에 제가 추가하지 않아서 그렇습니다.)

 

이런 식으로 하니 정상 동작을 했습니다.

 

 

3. 결론 및 느낀 점

mybatis 를 테스트하기 위해서 @MybatisTest를 이용했습니다.

하지만 내장 H2를 사용함에 따라서 mapper.xml의 postgreSQL에서 지원하는 기능을 찾지 못했습니다.

h2 의 mode를 이용해서 data source를 만든 후, 빈 주입하여 해결했습니다.

 

 

테스트 코드를 작성하기가 생각보다 어려웠습니다. SI에서는 왜 테스트 코드를 작성하지 않는 지 알 것 같았습니다.

공부해야 할 양도 많고, 시간이 없어서 쉽지 않았습니다.

 

하지만 추후 유지보수를 하거나 운영을 하기 위해서는 이러한 테스트 코드가 꼭 필요하다고 생각합니다.

그래야지만 내가 추가한 기능이 다른 서비스에 지장을 주지 않고 동작하는 지 바로 테스트할 수 있습니다.

 

만약 테스트 코드가 없다면 계속 Post man을 이용해서 요청을 해야 하고, 로컬 db나 개발계가 없다면 테스트하기가 쉽지 않습니다.

잘못된 요청이 올 경우에도 테스트를 해봐야 하는데 이 파라미터를 수동으로 변경하면서 테스트하기는 시간이 너무 걸립니다.

또한 새로운 팀원이 온다면, 테스트를 위한 post man 요청을 공유 해줘야 합니다.(제가 실제로 받았었습니다 ㅎㅎ...)

 

테스트 코드를 작성하기 위해서 서비스를 잘 분리하는 것도 중요하다는 것을 다시 한 번 알 수 있었습니다.

 

 

 

추후에는 jpa나 queryDSL로 변경해보고 싶네요.

mybatis를 이용해서 구현하다 보니 컴파일 단계에서 (Schema 구조 등)에러를 잡아주지 않아서 불편하네요...

 

반응형

'BackEnd > java' 카테고리의 다른 글

[Java] Integer 캐시 관련  (0) 2024.03.07