Konsist
GitHubSlack (kotlinlang)Twitter
  • 🚀GETTING STARTED
    • What is Konsist?
    • Getting Started
      • Add Konsist Dependency
      • Create First Konsist Test - Declaration Check
      • Create Secound Konsist Test - Architectural Check
    • Articles & Videos
  • ✅WRITING TESTS
    • Create The Scope
    • Declaration Filtering
    • Declaration Assertion
    • Architecture Assertion
    • Suppress Konsist Test
  • ✏️VERYFYING CODEBASE
    • Verify Classes
    • Verify Interfaces
    • Verify Functions
    • Verify Properties
    • Verify Generics
    • Verify Source Declarations
  • 📗FEATURES
    • Add Konsist Existing To Project (Baseline)
    • Debug Konsist Test
    • Declaration
    • Declaration Vs Property
    • Compiler Type Inference
    • Package Wildcard
    • Declaration References
    • Indirect Parents
    • Kotest Support
  • 🔍INSPIRATION
    • Starter Projects
    • Snippets
      • General Snippets
      • Android Snippets
      • Spring Snippets
      • Test Snippets
      • JUnit Snippets
      • Kotest Snippets
      • Architecture Snippets
      • Clean Architecture Snippets
      • Kotlin Serialization Snippets
      • Library Snippets
      • Generic Types Snippets
  • 🎓ADVANCED
    • Isolate Konsist Tests
    • Enable Full Command Line Logging
    • Dynamic Konsist Tests
      • Explicit Test Names
    • When Konsist API Is Not Enough
    • Additional JUnit5 Setup
    • Why There Are No Pre-defined Rules?
    • Konsist Snapshots
  • ❓HELP
    • Getting Help
    • Known Issues
      • java.lang.OutOfMemoryError: Java heap space
    • Compatibility
  • ℹ️OTHER
    • Changelog
    • Project Status
    • Contributing
    • Contributors
    • Assets And Logos
    • Open Source Licenses
    • Sponsor Konsist
Powered by GitBook
On this page
  • 1. Interfaces With Repository Annotation Should Have Repository Suffix
  • 2. Classes With RestController Annotation Should Have Controller Suffix
  • 3. Controllers Never Returns Collection Types
  • 4. Classes With RestController Annotation Should Reside In controller Package
  • 5. Classes With RestController Annotation Should Never Return Collection
  • 6. Service Classes Should Be Annotated With Service Annotation
  • 7. Entity Classes Should Have An Id Field
  • 8. DTO Classes Should Be Data Classes
  • 9. RestControllers Should Not Have State Fields
  • 10. Files With Domain Package Do Not Have Spring References
  • 11. Transactional Annotation Should Only Be Used On Default Or Public Methods That Are Not Part Of An Interface
  • 12. Every API Method In RestController With Admin Suffix Should Have PreAuthorize Annotation With ROLE_ADMIN
  • 13. Every Non-public Controller Should Have @PreAuthorize On Class Or On Each Endpoint Method
Edit on GitHub
Export as PDF
  1. INSPIRATION
  2. Snippets

Spring Snippets

PreviousAndroid SnippetsNextTest Snippets

Last updated 5 months ago

Konsist can be used to guard the consistency of the project.

1. Interfaces With Repository Annotation Should Have Repository Suffix

@Test
fun `interfaces with 'Repository' annotation should have 'Repository' suffix`() {
    Konsist
        .scopeFromProject()
        .interfaces()
        .withAnnotationOf(Repository::class)
        .assertTrue { it.hasNameEndingWith("Repository") }
}

2. Classes With RestController Annotation Should Have Controller Suffix

@Test
fun `classes with 'RestController' annotation should have 'Controller' suffix`() {
    Konsist
        .scopeFromProject()
        .classes()
        .withAnnotationOf(RestController::class)
        .assertTrue { it.hasNameEndingWith("Controller") }
}

3. Controllers Never Returns Collection Types

@Test
fun `controllers never returns collection types`() {
    /*
    Avoid returning collection types directly. Structuring the response as
    an object that contains a collection field is preferred. This approach
    allows for future expansion (e.g., adding more properties like "totalPages")
    without disrupting the existing API contract, which would happen if a JSON
    array were returned directly.
    */
    Konsist
        .scopeFromPackage("story.controller..")
        .classes()
        .withAnnotationOf(RestController::class)
        .functions()
        .assertFalse { function ->
            function.hasReturnType { it.isKotlinCollectionType }
        }
}

4. Classes With RestController Annotation Should Reside In controller Package

@Test
fun `classes with 'RestController' annotation should reside in 'controller' package`() {
    Konsist
        .scopeFromProject()
        .classes()
        .withAnnotationOf(RestController::class)
        .assertTrue { it.resideInPackage("..controller..") }
}

5. Classes With RestController Annotation Should Never Return Collection

@Test
fun `classes with 'RestController' annotation should never return collection`() {
    Konsist
        .scopeFromPackage("story.controller..")
        .classes()
        .withAnnotationOf(RestController::class)
        .functions()
        .assertFalse { function ->
            function.hasReturnType { it.hasNameStartingWith("List") }
        }
}

6. Service Classes Should Be Annotated With Service Annotation

@Test
fun `Service classes should be annotated with Service annotation`() {
    Konsist
        .scopeFromProject()
        .classes()
        .withNameEndingWith("Service")
        .assertTrue { it.hasAnnotationOf(Service::class) }
}

7. Entity Classes Should Have An Id Field

@Test
fun `Entity classes should have an Id field`() {
    Konsist
        .scopeFromProject()
        .classes()
        .withAnnotationOf(Entity::class)
        .assertTrue { clazz ->
            clazz.properties().any { property ->
                property.hasAnnotationOf(Id::class)
            }
        }
}

8. DTO Classes Should Be Data Classes

@Test
fun `DTO classes should be data classes`() {
    Konsist
        .scopeFromProject()
        .classes()
        .withNameEndingWith("DTO")
        .assertTrue { it.hasModifier(KoModifier.DATA) }
}

9. RestControllers Should Not Have State Fields

@Test
fun `RestControllers should not have state fields`() {
    Konsist
        .scopeFromProject()
        .classes()
        .withAnnotationOf(RestController::class)
        .objects()
        .withModifier(KoModifier.COMPANION)
        .assertTrue {
            it.properties().isEmpty()
        }
}

10. Files With Domain Package Do Not Have Spring References

@Test
fun `files with domain package do not have Spring references`() {
    Konsist.scopeFromProduction()
        .files
        .withPackage("..domain..")
        .assertFalse {
            it
                .imports
                .any { import ->
                    import.name.startsWith("org.springframework")
                }
        }
}

11. Transactional Annotation Should Only Be Used On Default Or Public Methods That Are Not Part Of An Interface

@Test
fun `Transactional annotation should only be used on default or public methods that are not part of an interface`() {
    Konsist.scopeFromProject()
        .functions()
        .withAnnotationOf(Transactional::class)
        .assertTrue {
            it.hasPublicOrDefaultModifier && it.containingDeclaration !is KoInterfaceDeclaration
        }
}

12. Every API Method In RestController With Admin Suffix Should Have PreAuthorize Annotation With ROLE_ADMIN

@Test
fun `every API method in RestController with 'Admin' suffix should have PreAuthorize annotation with ROLE_ADMIN`() {
    Konsist.scopeFromProject()
        .classes()
        .withAnnotationOf(RestController::class)
        .withNameEndingWith("Admin")
        .functions()
        .assertTrue {
            it.hasAnnotationOf(PreAuthorize::class) && it.text.contains("hasRole('ROLE_ADMIN')")
        }
}

13. Every Non-public Controller Should Have @PreAuthorize On Class Or On Each Endpoint Method

@Test
fun `every non-public Controller should have @PreAuthorize on class or on each endpoint method`() {
    Konsist.scopeFromProject()
        .classes()
        .withAnnotationOf(RestController::class)
        .filterNot { it.hasPublicModifier }
        .assertTrue { controller ->
            controller.hasAnnotationOf(PreAuthorize::class) ||
                    controller.functions()
                        .all { it.hasAnnotationOf(PreAuthorize::class) }
        }
}
🔍
Spring