Create First Konsist Test - Declaration Check
Konsist Declaration Checks
provide a powerful mechanism for validating the structural elements of the Kotlin codebase. These checks allow developers to enforce structural rules and coding conventions by verifying classes, interfaces, functions, properties, and other code declarations. Here few things that can be verified with Konsist:
All Use cases should reside in
usecase
specific packageRepository classes must implement Repository interface
All repository classes should have name ending with
Repository
data
classes should have only val propertiesTest classes should have test subject named
sut
...
Write First Declaration Check
Let's write a simple test to verify that all classes (all class declarations) residing in resides in controller
package are annotated with the RestController
annotation .
Overview
On a high level writing Konsist declaration check
requires 4 steps:
Let's take a closer look at each of these steps.
1. Create The Scope
The first step is to get a list of Kotlin files to be verified.
The Konsist
object is an entry point to the Konsist library.
Konsist
The scopeFromX
methods obtains the instance of the scope containing Kotlin project files. To get all Kotlin project files present in the project use the scopeFromProject
method:
// Define the scope containing all Kotlin files present in the project
Konsist.scopeFromProject() //Returns KoScope
2. Retrieve Declarations
Each file in the scope contains set of declarations like classes, properties functions etc. (see Declaration). To write this declaration check for all classes present in the scope query classes using classes
method :
Konsist.scopeFromProject()
// Get scope classes
.classes()
3. Filter Declarations
In this project controllers are defined as classes annotated with RestController
annotation. Use withAllAnnotationsOf
method to filter classes with with RestController
annotation:
Konsist.scopeFromProject()
.classes()
// Filter classes annotated with 'RestController'
.withAllAnnotationsOf(RestController::class)
4. Define Assertion
To performa assertion use the assertTrue
method:
Konsist.scopeFromProject()
.classes()
.withAllAnnotationsOf(RestController::class)
.assertTrue {
// Define the assertion
}
To verify that classes are located in the controller
package, use the resideInPackage
method inside assertTrue
block:
Konsist.scopeFromProject()
.classes()
.withAllAnnotationsOf(RestController::class)
.assertTrue {
// Check if classes are located in the controller package
it.resideInPackage("..controller")
}
This verification applies to the entire collection of previously filtered classes, rather than examining just one class in isolation.
Wrap Konsist Code In Test
The declaration validation logic should be protected through automated testing. By wrapping Konsist checks within standard testing frameworks such as JUnit or KoTest, you can verify these rules with each Pull Request:
class ControllerClassKonsistTest {
@Test
fun `classes annotated with 'RestController' annotation reside in 'controller' package`() {
// 1. Create a scope representing the whole project (all Kotlin files in project)
Konsist.scopeFromProject()
// 2. Retrieve class declarations
.classes()
// 3. Filter classes annotated with 'RestController'
.withAllAnnotationsOf(RestController::class)
// 4. Define the assertion
.assertTrue { it.resideInPackage("..controller..") }
}
}
Note that test class has a KonsistTest
suffix. This is the recommended approach to name classes containing Konsist tests.
Summary
This section described the basic way of writing Konsist declaration test. To get a better understanding of how Konsist API works see https://github.com/LemonAppDev/konsist-documentation/blob/main/getting-started/getting-started/broken-reference/README.md and Debug Konsist Test sections.
The above test will execute multiple assertions per test (all controllers will be verified in a single test). If you prefer better isolation each assertion can be executed as a separate test. See the Dynamic Konsist Tests page.
Last updated