작성
·
938
1
안녕하세요. 강의 잘 듣고있습니다 :)
allopen 관련 질문이 하나 있는데요.
이전 강의에서 UserService를 코틀린으로 리팩토링했었는데 해당 과정부터 이번 BookService 리팩토링 강의까지 allopen 관련 에러가 발생하는 것 같습니다.
Failed to resolve parameter [com.group.libraryapp.domain.user.UserRepository userRepository] in constructor [public com.group.libraryapp.service.user.UserServiceTest(com.group.libraryapp.domain.user.UserRepository,com.group.libraryapp.service.user.UserService)]: Failed to load ApplicationContext
org.junit.jupiter.api.extension.ParameterResolutionException: Failed to resolve parameter [com.group.libraryapp.domain.user.UserRepository userRepository] in constructor [public com.group.libraryapp.service.user.UserServiceTest(com.group.libraryapp.domain.user.UserRepository,com.group.libraryapp.service.user.UserService)]: Failed to load ApplicationContext
at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameter(ExecutableInvoker.java:239)
at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameters(ExecutableInvoker.java:183)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:74)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestClassConstructor(ClassBasedTestDescriptor.java:355)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateTestClass(ClassBasedTestDescriptor.java:302)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:79)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:280)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:272)
리팩토링을 완료하고 테스트 코드를 실행시켜보면 위와 같은 에러가 발생합니다.
하지만 UserService의 클래스와 메소드들에 open을 붙여주면 정상적으로 돌아가더라구요.
plugins {
id 'org.springframework.boot' version '2.6.8'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.6.21'
id 'org.jetbrains.kotlin.plugin.jpa' version '1.6.21'
id "org.jetbrains.kotlin.plugin.allopen" version "1.6.21"
}
allOpen {
annotation("javax.persistence.Entity")
annotation("javax.persistence.MappedSuperclass")
annotation("javax.persistence.Embeddable")
}
group = 'com.group'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'org.jetbrains.kotlin:kotlin-reflect:1.6.21'
implementation 'org.junit.jupiter:junit-jupiter:5.7.0'
implementation "org.assertj:assertj-core:3.11.1"
implementation "org.springframework.boot:spring-boot-starter-test"
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation "org.assertj:assertj-core:3.11.1"
}
tasks.named('test') {
useJUnitPlatform()
}
compileKotlin {
kotlinOptions {
jvmTarget = "11"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "11"
}
}
현재 제 build.gradle 파일도 같이 첨부합니다.
감사합니다 :)
답변 3
1
안녕하세요, 영식님!!!
build.gradle까지 첨부주시고~ 감사합니다 😊😊
아이고~ 맞습니다!!! 아마 16강에서 언급될텐데요! @Service
와 같은 스프링 빈을 코틀린에서 활용하기 위해서는 적어주신 플러그인이 필요합니다!!
플러그인을 적용했음에도 바이트코드로 확인하셨을 때 잘동작하지 않을 때는 1) gradle refresh를 해보시고, 2) IntelliJ를 종료했다가 재시작해보시면 될거에요!!
스프링 공식 문서로는 https://kotlinlang.org/docs/all-open-plugin.html 에서 참고하실 수 있습니다!!
추가로, 말씀해주신 allOpen
의 경우는 명시적으로 적용대상을 적어주어야 하는데, 현재는 javax.persistence.Entity
와 같이 JPA 관련 어노테이션이 붙은 경우에만 적용되서 @Service
클래스에는 적용되지 않은 것입니다.
감사합니다! 🙇🙇
1
자문자답합니다.
id "org.jetbrains.kotlin.plugin.spring" version "1.6.21"
build.gradlew에 위 라인 추가해주니까 정상 동작합니다!
1
추가적으로 바이트코드로 변환해봐도
public final class com/group/libraryapp/service/book/BookService {
@Lorg/springframework/stereotype/Service;()
// access flags 0x11
public final saveBook(Lcom/group/libraryapp/dto/book/request/BookRequest;)V
이런식으로 final이 붙어있는걸 보아 allopen이 제대로 적용되지 않는 것 같아요.