We have Spring application unit tested using JMockit mock framework. Now we would like to write new tests in Kotlin using MockK. Almost everything seems to work fine but we can't figure out how to mock beans autowired by Spring. With JMockit we used to use @Capturing annotation that extended the mocking also on classes implementing the mocked interface. How can I achive similar behavior of a mock in the MockK framework?
Asked
Active
Viewed 892 times
0
-
I think the basic answer would be not as easy as using one annotation, but first I'd like to understand in general what is the problem. Without comparison to JMockit. You want to Autowire mocks, am I right? Why you just don't do `@Bean fun bean(): Type = mockk()` I know that support of Spring in mockk is limmited, but just want to understand pain points and use-cases. – oleksiyp Sep 01 '18 at 21:32
-
Thank you very much, you are right, it is indeed possible to do it the way you suggest. With combination of relaxed mock I was able to make it work. By the way is there a way to set default value for relaxed mock to null rather than the default value? – Klugi Sep 04 '18 at 07:21
-
There is not, but you can request a feature via GH issues – oleksiyp Sep 05 '18 at 08:03
2 Answers
2
Bringing oleksiyp comments to an answer
Currently, Mockk doesn't have that kind of behavior. Its support to Spring is limited, but there's a workaround using Spring itself:
You can create a bean
however you want, even in Integration Tests. When creating a bean, you can instantiate a mock:
@Bean
fun bean(): BeanType = mockk()
Then, when this bean is autowired, it will return the mocked instance, and you'll be able to set it's behavior using Mockk's DSL as usual.

LeoColman
- 6,950
- 7
- 34
- 63
-
This does not seem to work anymore(if it was ever working). I am on spring-boot-2.3.11 & spring-test-5.2.15. The test execution throws up an error saying "java.lang.IllegalStateException: Test classes cannot include @Bean methods". – Raj Jul 15 '21 at 11:38
0
Spring documentation recommends that all your components be autowired through the constructor. If you follow that convention you wouldn't have this problem.
To be specific, the recommendation is as following...
@RestController
class SomeRandomController(
@Autowired private val ARepository: aRepository,
@Autowired private val BRepository: bRepository,
@Autowired private val CRepository: cRepository
){ etc ...}
Then in your test you will need the following lines:
val aRepository = mockk<ARepository>(relaxed = true)
val bRepository = mockk<BRepository>(relaxed = true)
val cRepository = mockk<CRepository>(relaxed = true)
val controller = SomeRandomController(aRepository, bRepository, cRepository)

lfmunoz
- 822
- 1
- 9
- 16