Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlintest not executing test when using springmockk

I tried to write an integration test for my kotlin spring application. For this I am using the kotlintest framework. As I need to mock one of the beans in my application I also added mockk with the springmockk extension. After adding the springmockk extension the test no longer got executed.

I noticed this happens as soon as springmockk is added to the gradle testImplement dependencies, it does not even have to be imported in the application code itself.

buildscript {
    ext.kotlin_version = '1.3.21'
    ext.kotlintestVersion='3.4.2'
    ext.spring_boot_version='2.1.4.RELEASE'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBoot_version")
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlin_version")
    }
}

...

dependencies {
    ...
    testImplementation("org.springframework.boot:spring-boot-starter-test:$springBoot_version") {
    testImplementation("io.kotlintest:kotlintest-runner-junit5:$kotlintestVersion")
    testImplementation("io.kotlintest:kotlintest-extensions-spring:$kotlintestVersion")
    testImplementation("io.mockk:mockk:1.9.3")
//    testImplementation("com.ninja-squad:springmockk:2.0.0")
}

On github I found an issue which sadly has been closed already without any proper way of using these two frameworks together: https://github.com/Ninja-Squad/springmockk/issues/26

Edit:

This is an example test, which is working when using mockkito but not when using springmockk.

@ExtendWith(SpringExtension::class)
@SpringBootTest
@AutoConfigureMockMvc
@WithMockUser(authorities = ["ROLE_TESTUSER"])
internal class MockTest : AnnotationSpec() {

    override fun listeners() = listOf(SpringListener)

    @Autowired
    lateinit var mockMvc: MockMvc

    @MockkBean
    lateinit var securityHelper: SecurityHelper

    @Test
    fun integrationTest() {
        whenever(securityHelper.someFunction()).thenReturn("test")
        mockMvc.perform(MockMvcRequestBuilders.get("/some/endpoint")
        ).andExpect(MockMvcResultMatchers.status().isOk)
    }
}

./gradlew test --rerun-tasks output:

> Configure project :
Property 'app.env' not found using profile dev: use -Papp.env=dev to define the environment for 'SPRING_PROFILES_ACTIVE'

> Task :compileKotlin

BUILD SUCCESSFUL in 56s
5 actionable tasks: 5 executed
like image 441
JJensen Avatar asked Nov 16 '22 17:11

JJensen


1 Answers

Mock Bean with springMockk

To use @MockkBean you need to add springmockk and remove mockito core from the spring-boot-starter-test in your gradle file like:

testImplementation("io.mockk:mockk:1.9.3")
testImplementation("com.ninja-squad:springmockk:2.0.2")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
    exclude(module = "mockito-core")
}

Then your bean should be mocked with:

@MockkBean
lateinit var securityHelper: SecurityHelper

Mock Bean with MockK only

You can mock the bean just using mockK by modifying the @TestConfiguration and setting the profile of the mock Bean to be the same as the one used for your test:

  @TestConfiguration
  class ControllerTestConfig {

    @Bean
    @Profile("test")
    fun securityHelper(): SecurityHelper {
      val securityHelperMock: SecurityHelper = mockk(relaxed = true)
      every { securityHelperMock.someFunction() } returns "test"
      return securityHelperMock
    }
  }

You can force use the TestConfig by putting it in your @SpringBootTest:

@SpringBootTest(
    classes = [YourApplication::class, ControllerTestConfig::class]
)
like image 72
Sylhare Avatar answered Dec 30 '22 21:12

Sylhare