ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Execution failed for task ':test' 해결방법
    Spring boot 2023. 6. 19. 17:39

     

    들어가기 전에

    QueryDSL 을 사용하기 위해 환경을 구성하던 중 만나게 된 Execution failed for task ':test'. 관련 오류에 관한 기록이다.

     

     

    콘솔에 찍힌 오류

    contextLoads() FAILED
        java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:142
            Caused by: org.springframework.beans.factory.BeanCreationException at AbstractAutowireCapableBeanFactory.java:1770
                Caused by: org.hibernate.AnnotationException at CollectionBinder.java:1568

     

    출력된 오류를 검색해본 결과 가장 간단한 방법은 Test 폴더에 작성된 @SpringBootTest 어노테이션을 주석 처리하거나 Test 폴더를 삭제하는 것이다.

     

    build.gradle.kts 파일의 작성된 Test 작업관련 구성을 삭제하는 것도 가능하다.

    tasks.withType<Test> {
    	useJUnitPlatform()
    }

     

    그런데, 삭제하는걸로 마무리하면 테스트 코드를 사용할 수가 없으니 테스트 코드를 작성 가능한 환경으로 구성하고 싶어졌다.

     

    초기 프로젝트가 아닌 이상 다양한 도메인 객체들이 연관되어 코드 작성이 되어 있을 것이다.

    도메인 객체들 `mappedBy` 요소가 빠짐없이 작성되어 있어야 내가 테스트하고자 하는 객체를 확인해볼 수 있다.

     

    구현할 테스트 코드

    @SpringBootTest
    @Transactional
    class NativeBackendApplicationTests {
    
        @PersistenceContext
        EntityManager entityManager; // 스프링데이터 jpa에서 자동 빈 주입 , @Autowired 사용시 빈등록 코드를 별도로 직접 작성하여 주입해야한다.
    
        @Test
        void contextLoads() {
            Hello hello = new Hello();
            entityManager.persist(hello);
            JPAQueryFactory query = new JPAQueryFactory(entityManager); QHello qHello = new QHello("hello");
            Hello result = query
                    .selectFrom(qHello)
                    .fetchOne();
    
            Assertions.assertThat(result).isEqualTo(hello); //Querydsl Q타입이 정상 동작하는가?
            Assertions.assertThat(result.getId()).isEqualTo(hello.getId());//롬복 @Getter확인
        }
    }

     

    Hello 도메인 객체를 테스트 하기 위해 내가 연결해놓은 데이터베이스의 Hello 테이블이 존재해야 한다.

    spring.jpa.hibernate.ddl-auto: none 으로 설정되어 있기 때문이다. 만약 create or create-drop 으로 작성되어 있으면 굳이 Hello 테이블이 존재하지 않아도 되지만 기존 테이블 구조를 유지하면서 테스트 하기 위해서는 none 값으로 구성해야한다.

     

    Hello 도메인 객체에 @Getter 를 선언해 필드값을 가져올 수 있게 구성한다.

    @Entity
    @Getter
    @Setter(AccessLevel.PRIVATE)
    @AllArgsConstructor
    public class Hello {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        
        protected Hello(){}
    }

     

    또한, JPA 는 쿼리문을 수행할 때 트랜잭션 안에서 동작해야되기 때문에 @Transactional 어노테이션을 사용한다.

     

    위에서 제시한 내용을 모두 지키고 테스트 코드를 실행하게 되면 성공할 것이다.

    오후 5:05:41: Executing 'build'...
    
    > Task :compileJava
    > Task :processResources
    > Task :classes
    > Task :resolveMainClassName
    > Task :bootJar
    > Task :jar
    > Task :assemble
    > Task :compileTestJava
    > Task :processTestResources NO-SOURCE
    > Task :testClasses
    
    > Task :test
    OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
    2023-06-19T17:05:59.818+09:00  INFO 14904 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
    2023-06-19T17:05:59.821+09:00  INFO 14904 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
    2023-06-19T17:05:59.865+09:00  INFO 14904 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
    
    > Task :check
    > Task :build
    
    BUILD SUCCESSFUL in 18s
    7 actionable tasks: 7 executed
    오후 5:06:00: Execution finished 'build'.

     

    Tip.
    내가 수행한 쿼리문을 실제 데이터베이스 테이블에 접속해 확인해도 데이터가 들어가있지 않다.
    왜냐하면, 테스트 코드에서 트랜잭션을 수행하게 되었을 때 rollback 명령이 기본값으로 잡혀있기 때문이다.
    기본값으로 rollback 이 잡혀있지 않게되면 테스트코드로 수행하는 쿼리 명령이 데이터베이스의 반영되어 데이터가 변경되기 때문에 rollback 이 기본값으로 잡혀있는 것이다.

     

    이렇게 해서 Execution failed for task ':test' 오류를 해결해 테스트 관련 파일과 의존성을 삭제하지 않고도 정상 build 하게 환경구성을 할 수 있다.

Designed by Tistory.