jwsinner
jwsinner

Reputation: 378

Testing Kotlin Extension Functions with Spring

I have a controller that gets a specific service based on a customer name:

@RestController
class BasicController(){

    @Autowired
    private lateinit var services: List<BasicService<*>>

    private var service: BasicService<*>? = null

    @GetMapping("/{customer}")
    fun getAll(@PathVariable customer: String): ResponseEntity<String>{
        service = services.getServiceByCustomer(customer)
        /... code w/return value .../
    }
}

I have a file Extensions.kt with the following:

fun <T: BasicService> List<T>.getServiceByCustomer(customer: String): T?{
    return this.find{
        it::class.simpleName?.contains(customer, ignoreCase = true) == true
    }
}

Is it possible to return a mock of service when services.getServiceByCustomer is called similar to `when`(mock.function(anyString())).thenReturn(value)?

I've tried using mockK with the following:

mockkStatic("path.to.ExtensionsKt")
every {listOf(service).getServiceByCustomer)} returns service

But I don't think I'm using that properly... I'm currently using com.nhaarman.mockitokotlin2 but have tried io.mockk

Upvotes: 2

Views: 374

Answers (1)

Jo&#227;o Dias
Jo&#227;o Dias

Reputation: 17500

You just need to use a customer that actually matches the simple name of the mocked service. You don't need or even should mock the extension function. Try the following:

class BasicControllerTest {

    @MockK
    private lateinit var basicService: BasicService

    private lateinit var basicController: BasicController

    @BeforeEach
    fun setUp() {
        clearAllMocks()

        basicController = BasicController(listOf(basicService))
    }
}

Additionally, consider using constructor injection instead of field injection:

@RestController
class BasicController(private val services: List<BasicService<*>>){

    private var service: BasicService<*>? = null

    @GetMapping("/{customer}")
    fun getAll(@PathVariable customer: String): ResponseEntity<String>{
        service = services.getServiceByCustomer(customer)
        /... code w/return value .../
    }
}

Finally, consider testing the Controllers with @WebMvcTest instead of regular unit tests. Check more info here https://www.baeldung.com/spring-boot-testing#unit-testing-with-webmvctest.

Upvotes: 1

Related Questions