This is a none Spring Boot project.
I try to use mockk() to mock a bean in the controller tests, but failed.
The PostController depends on bean PostRepository, here try to use a mockk() bean to mock the PostRepository in our test config.
@SpringJUnitConfig(classes = [PostControllerTest.TestConfig::class])
class PostControllerTest {
companion object {
private val log = LoggerFactory.getLogger(PostControllerTest::class.java)
}
@Configuration(proxyBeanMethods = false)
@ComponentScan(basePackageClasses = [PostController::class])
internal class TestConfig {
@Bean
@Primary
fun postRepository(): PostRepository = mockk<PostRepository>()
}
@Autowired
lateinit var posts: PostRepository
lateinit var client: WebTestClient
@BeforeEach
fun setup() {
log.debug("calling setup...")
client = WebTestClient.bindToController(PostController::class)
.configureClient()
.build()
}
@AfterEach
fun teardown() {
clearAllMocks()
}
@Test
fun `get post by id`() = runTest {
val id = UUID.randomUUID().toString()
coEvery { posts.findById(any()) } returns
Post(
id = id,
title = "test title",
content = "content of test title"
)
client.get().uri("/posts/$id")
.exchange()
.expectStatus().isOk
.expectBody().jsonPath("$.title").isEqualTo("test title")
coVerify(exactly = 1) { posts.findById(any()) }
}
}
The example project used the latest Spring 6.1.x WebFlux, Kotlin(1.9.22)/Kotlin Coroutines(1.7.3), and Java 21.
Check source codes here, https://github.com/hantsy/spring-reactive-sample/tree/master/kotlin-co
In before experience, I applied same mode which used Mockito to mock beans in Java codes, it worked.
This actually makes a lot of sense.
Mockkalone isn't prepared to work with Spring. It is just a mocking library and so when you do this:it will try to recognize the controller, but that won't happen because at this point the Spring
WebTestClienthas no idea where to pick up thepostsrepository.For your example what you probably need to do is something slightly different like this:
By handing in the instance of the controller with your mocked repository, then the
WebTestClientwill be able to recognize the complete controller and I'm pretty sure this will work for you. The reason being is that I have reproduced the exact same404problem you are having in one of my projects using a similar code like your example and after changing it, it worked perfectly.However if you are working with
mockkand want to mock spring beans, then it is probably better to use something different called Spring MockK. It works much in same way asMockitodoes, but it is more adapted to work in aKotlinstyle.