How to write #Nested test classes in kotlin - kotlin

When writing a junit test:
internal class MyTest {
#org.junit.jupiter.api.Nested
class MyInnerClass {
}
}
A warning is displayed by my code editor (IntelliJ)
Only non-static nested classes can serve as #Nested test classes.
How to write a nested classes in junit tests in kotlin?

When using #Nested classes in kotlin they need the prefix inner as only inner classes can be used as nested classes.
Only non-static nested classes (i.e. inner classes) can serve as
#Nested test classes.
https://junit.org/junit5/docs/current/user-guide/#writing-tests-nested
Your code should look somewhat like this:
internal class MyTest {
#Nested
inner class MyInnerClass {
#Test
fun customTest() {
//TODO: do something
}
}
}

Related

Mocking Gradle javaexec calls with mockK

Currently a beginner with mockK as it relates to developing Gradle plugin code in Kotlin. Suppose I have this class:
abstract class MyDomainObjectClass #Inject constructor(private val execOps: ExecOperations) {
abstract val mainClass: Property<String>
fun run() {
execOps.javaexec {
// ...
}
}
}
What I want to do is to construct a MyDomainObjectClass (normally constructed using something like ObjectFactory.newInstance()) in such a way that I can pass in a mocked ExecOperations, so that I can verify that the javaexec call is called exactly once (with the verification possibly involving mainClass, if I can find a way to involve it).
Is there a way I can satisfy all these requirements, or am I better off with a constructed mock of MyDomainObjectClass (stubbing in mainClass in the process)?

Pointcut expression to match all public methods in all classes of my application except few packages and classes

I want to match all public methods of all classes of my application(not the dependency library classes) except one class and except classes in one package.
Kotlin class:
#Pointcut("execution(public * com.company.app..*.*(..))")
fun allApplicationCode() {}
#Pointcut("!execution(* * com.company.app.configuration..*.*(..))")
fun notConfigurationPackage() {}
#Pointcut("!execution(* * com.company.app..FlywayConfiguration.*(..))")
fun notFlywayConfigurationClass() {}
#Around("allApplicationCode() && notConfigurationPackage() && notFlywayConfigurationClass()")
fun logExecutionTime(joinPoint: ProceedingJoinPoint): Any {
//code
}
I get error regarding the Pointcut expressions in notConfigurationPackage() and notFlywayConfigurationClass()
Is it a problem if I want to mention "*" explicitly for access modifier?

How can I run Nested Test in kotest?

I'm trying to migrate test framework from JUnit 5 to kotest.
I selected Annotation Spec at first (to check compatibility), but Nested Annotation doesn't work as expected
Sample code is below
class Outside : AnnotationSpec() {
#Test
fun runOutside() { }
#Nested
inner class Inside() {
#Test
fun runInside() { }
}
}
runOutside runs well, but runInside doesn't. The error message is java.lang.IllegalArgumentException: object is not an instance of declaring class
What's wrong ? is this a bug ?

How to create a TestContainers base test class in Kotlin with JUnit 5

I am trying to use Neo4j TestContainers with Kotlin, Spring Data Neo4j, Spring Boot and JUnit 5. I have a lot of tests that require to use the test container. Ideally, I would like to avoid copying the container definition and configuration in each test class.
Currently I have something like:
#Testcontainers
#DataNeo4jTest
#Import(Neo4jConfiguration::class, Neo4jTestConfiguration::class)
class ContainerTest(#Autowired private val repository: XYZRepository) {
companion object {
const val IMAGE_NAME = "neo4j"
const val TAG_NAME = "3.5.5"
#Container
#JvmStatic
val databaseServer: KtNeo4jContainer = KtNeo4jContainer("$IMAGE_NAME:$TAG_NAME")
.withoutAuthentication()
}
#TestConfiguration
internal class Config {
#Bean
fun configuration(): Configuration = Configuration.Builder()
.uri(databaseServer.getBoltUrl())
.build()
}
#Test
#DisplayName("Create xyz")
fun testCreateXYZ() {
// ...
}
}
class KtNeo4jContainer(val imageName: String) : Neo4jContainer<KtNeo4jContainer>(imageName)
How can I extract the databaseServer definition and the #TestConfiguration? I tried different ways of creating a base class and having the ContainerTest extend it, but it is not working. From what I understand, static attriubutes are not inherited in Kotlin.
Below my solution for sharing same container between tests.
#Testcontainers
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
abstract class IntegrationTest {
companion object {
#JvmStatic
private val mongoDBContainer = MongoDBContainer(DockerImageName.parse("mongo:4.0.10"))
.waitingFor(HostPortWaitStrategy())
#BeforeAll
#JvmStatic
fun beforeAll() {
mongoDBContainer.start()
}
#JvmStatic
#DynamicPropertySource
fun registerDynamicProperties(registry: DynamicPropertyRegistry) {
registry.add("spring.data.mongodb.host", mongoDBContainer::getHost)
registry.add("spring.data.mongodb.port", mongoDBContainer::getFirstMappedPort)
}
}
}
The key here is to not use #Container annotation as it will close just created container after your first test subclass executes all tests.
Method start() in beforeAll() initialize container only once (upon first subclass test execution), then does nothing while container is running.
By theory we shouldn't have to do this hack, based on:
https://www.testcontainers.org/test_framework_integration/junit_5/
...container that is static should not be closed until all of tests of all subclasses are finished, but it's not working that way and I don't know why. Would be nice to have some answer on that :).
I've had the same issue (making Spring Boot + Kotlin + Testcontainers work together) and after searching the web for (quite) a while I found this nice solution: https://github.com/larmic/testcontainers-junit5. You'll just have to adopt it to your database.
I faced very similar issue in Kotlin and spring boot 2.4.0.
The way you can reuse one testcontainer configuration can be achieved through initializers, e.g.:
https://dev.to/silaev/the-testcontainers-mongodb-module-and-spring-data-mongodb-in-action-53ng or https://nirajsonawane.github.io/2019/12/25/Testcontainers-With-Spring-Boot-For-Integration-Testing/ (java versions)
I wanted to use also new approach of having dynamicProperties and it worked out of a boxed in java. In Kotlin I made sth like this (I wasn't able to make #Testcontainer annotations working for some reason). It's not very elegant but pretty simple solution that worked for me:
MongoContainerConfig class:
import org.testcontainers.containers.MongoDBContainer
class MongoContainerConfig {
companion object {
#JvmStatic
val mongoDBContainer = MongoDBContainer("mongo:4.4.2")
}
init {
mongoDBContainer.start()
}
}
Test class:
#SpringBootTest(
classes = [MongoContainerConfig::class]
)
internal class SomeTest {
companion object {
#JvmStatic
#DynamicPropertySource
fun setProperties(registry: DynamicPropertyRegistry) {
registry.add("mongodb.uri") {
MongoContainerConfig.mongoDBContainer.replicaSetUrl
}
}
}
Disadvantage is this block with properties in every test class what suggests that maybe approach with initializers is desired here.

create nested class (kt) for existing class (java), extensions

does Kotlin compiler allow extending classes with inner and/or nested classes and if so what's the correct syntax?
in EnclosingClass.java
class EnclosingJavaClass {
class NestedJavaClass1 {}
class NestedJavaClass2 {}
// ...
}
this is what i'm unsure of below,
in EnclosingClassExtensions.kt
class EnclosingJavaClass.NestedKotlinClass {
// ...
}
assuming that EnclosingClass.java cannot be modified (eg: library code), can i declare somehow a EnclosingClass.SomeNewKotlinClass ?