Support for Spring Boot integration tests written in Kotlin using MockK instead of Mockito.
Spring Boot provides @MockBean
and @SpyBean
annotations for integration tests, which create mock/spy beans using Mockito.
This project provides equivalent annotations MockkBean
and SpykBean
to do the exact same thing with MockK.
All the Mockito-specific classes of the spring-boot-test library, including the automated tests, have been cloned, translated to Kotlin, and adapted to MockK.
This library thus provides the same functionality as the standard Mockito-based Spring Boot mock beans.
For example (using JUnit 5, but you can of course also use JUnit 4):
@ExtendWith(SpringExtension::class)
@WebMvcTest
class GreetingControllerTest {
@MockkBean
private lateinit var greetingService: GreetingService
@Autowired
private lateinit var controller: GreetingController
@Test
fun `should greet by delegating to the greeting service`() {
every { greetingService.greet("John") } returns "Hi John"
assertThat(controller.greet("John")).isEqualTo("Hi John")
verify { greetingService.greet("John") }
}
}
Add this to your dependencies:
testImplementation("com.ninja-squad:springmockk:4.0.2")
If you want to make sure Mockito (and the standard MockBean
and SpyBean
annotations) is not used, you can also exclude the mockito dependency:
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(module = "mockito-core")
}
Add this to your dependencies:
<dependency>
<groupId>com.ninja-squad</groupId>
<artifactId>springmockk</artifactId>
<version>4.0.2</version>
<scope>test</scope>
</dependency>
@MockkBean(relaxed = true)
or @MockkBean(relaxUnitFun = true)
. In some situations, the beans that need to be spied are JDK proxies. In recent versions of Java (Java 16+ AFAIK),
MockK can't spy JDK proxies unless you pass the argument --add-opens java.base/java.lang.reflect=ALL-UNNAMED
to the JVM running the tests.
Not doing that and trying to spy on a JDK proxy will lead to an error such as
java.lang.IllegalAccessException: class io.mockk.impl.InternalPlatform cannot access a member of class java.lang.reflect.Proxy (in module java.base) with modifiers "protected"
To pass that option to the test JVM with Gradle, configure the test task with
tasks.test {
// ...
jvmArgs(
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED"
)
}
For Maven users:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
@field:YourQualifier
to apply it on your beans. ./gradlew build