I tried to write a test code using 'rest docs' in Spring Boot with kotlin. I am having an issue with injecting MockMvc to my test class. No qualifying bean of type Shouldn't @AutoConfigureMockMvc, @AutoConfigureRestDoc, @ExtendWith(RestDocumentationExtension::class) annotations be automatically wired? I don't know why the bean is not being auto-injected.
- build.gradle.kts
plugins {
id("org.springframework.boot") version "2.7.15-SNAPSHOT"
id("io.spring.dependency-management") version "1.0.15.RELEASE"
// spring rest doc, gradle version 7 이상
id("org.asciidoctor.jvm.convert") version "3.3.2"
kotlin("jvm") version "1.6.21"
kotlin("plugin.spring") version "1.6.21"
kotlin("plugin.jpa") version "1.6.21"
kotlin("kapt") version "1.7.10"
}
val asciidoctorExt by configurations.creating
java {
sourceCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
maven { url = uri("https://repo.spring.io/milestone") }
maven { url = uri("https://repo.spring.io/snapshot") }
}
dependencies {
// jpa
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
runtimeOnly("com.h2database:h2")
// queryDSL
implementation("com.querydsl:querydsl-jpa:5.0.0")
kapt("com.querydsl:querydsl-apt:5.0.0:jpa")
// kotest + mockk
testImplementation("io.kotest:kotest-runner-junit5-jvm:4.4.3")
testImplementation("io.kotest:kotest-assertions-core-jvm:4.4.3")
implementation("io.kotest:kotest-extensions-spring:4.4.3")
testImplementation("io.mockk:mockk:1.13.5")
// api doc(rest doc)
asciidoctorExt("org.springframework.restdocs:spring-restdocs-asciidoctor")
testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
}
//tasks.withType<Test> {
// useJUnitPlatform()
//}
//tasks.test {
// outputs.dir(snippetsDir)
//}
val snippetsDir by extra {
file("build/generated-snippets")
}
tasks {
asciidoctor {
dependsOn(test)
configurations("asciidoctorExt")
baseDirFollowsSourceFile() // 3
inputs.dir(snippetsDir)
}
register<Copy>("copyDocument") { // 4
dependsOn(asciidoctor)
from(file("build/docs/asciidoc/index.html"))
into(file("src/main/resources/static/docs"))
}
bootJar {
dependsOn("copyDocument") // 5
}
}
- test code
@AutoConfigureMockMvc
@AutoConfigureRestDocs
@ExtendWith(RestDocumentationExtension::class)
class ControllerTest(
@Autowired
private val mockMvc: MockMvc,
@MockBean private val lectureService: LectureService,
) : BehaviorSpec({
...
...
val result = mockMvc.post("/api/lectures") {
contentType = MediaType.APPLICATION_JSON
content = objectMapper.writeValueAsString(lectureCreateRequest)
}.andExpect {
status { isCreated() }
}.andReturn()
})
- error message
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.example.lecturereservationsystem.lecture.controller.LectureControllerTest': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.test.web.servlet.MockMvc' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowire(AbstractAutowireCapableBeanFactory.java:387)
at io.kotest.spring.SpringAutowireConstructorExtension.instantiate(SpringListener.kt:136)
at io.kotest.engine.spec.InstantiateSpecKt.createAndInitializeSpec(instantiateSpec.kt:22)
at io.kotest.engine.spec.SpecExecutor.createInstance(SpecExecutor.kt:53)
at io.kotest.engine.spec.SpecExecutor.execute(SpecExecutor.kt:40)
at io.kotest.engine.launchers.DefaultSpecLauncher$sequential$$inlined$forEach$lambda$1$1.invokeSuspend(DefaultSpecLauncher.kt:56)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.test.web.servlet.MockMvc' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
... 13 more
21:37:51.514 [SpringContextShutdownHook] DEBUG org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@58ceb491, started on Mon Jul 24 21:37:51 KST 2023
Process finished with exit code 255
Error creating bean with name 'com.example.lecturereservationsystem.lecture.controller.LectureControllerTest': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.test.web.servlet.MockMvc' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}