From 9a4f31571414d76c18f3fb82cea0c42b523e7d61 Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Sat, 8 Jan 2022 22:06:33 +0700 Subject: [PATCH] replace generated `Archtest` by `TechnicalStructureTest` Since the generated application is modelled after a simple layered architecture we can provide a generated ArchUnit test that uses `Architectures.layeredArchitecture()` as a nice example of a higher abstraction architecture rule. This will assert even more dependencies for correctness than before (for example no dependencies from repositories to services). Furthermore, by specifying an exact list of which layer is allowed to access which other layer, instead of forbidding specific dependencies from one layer to another, we remove one potential source of accidental violation. E.g., by forbidding `service -> web` we can still have accesses like `services -> some_utils_no_one_cares_about -> web`. If we specify that no other layer may access web (because all accesses are via REST, etc., and not from other Java code), we can make sure that there are no accidental dependencies through some unexpected packages. I've also replaced the manual import via `new ClassFileImporter()...importPackages(..)` by ArchUnit's JUnit 5 support. The dependency was already correct anyway, and it allows to write the test a little more concisely and automatically brings caching between multiple rules that import the same classes. Resolves: #17520 --- .../__snapshots__/generator.spec.mjs.snap | 2 +- generators/server/files.js | 4 +- .../src/test/java/package/ArchTest.java.ejs | 47 ----------------- .../package/TechnicalStructureTest.java.ejs | 44 ++++++++++++++++ .../app-client-custom-path.spec.js.snap | 4 +- test/__snapshots__/app.spec.js.snap | 52 +++++++++---------- test/__snapshots__/server.spec.js.snap | 4 +- .../__snapshots__/app-blueprint.spec.js.snap | 8 +-- .../scoped-blueprint.spec.js.snap | 4 +- 9 files changed, 83 insertions(+), 86 deletions(-) delete mode 100644 generators/server/templates/src/test/java/package/ArchTest.java.ejs create mode 100644 generators/server/templates/src/test/java/package/TechnicalStructureTest.java.ejs diff --git a/generators/server/__snapshots__/generator.spec.mjs.snap b/generators/server/__snapshots__/generator.spec.mjs.snap index f4e59dcf766..fe8e9c9e6f5 100644 --- a/generators/server/__snapshots__/generator.spec.mjs.snap +++ b/generators/server/__snapshots__/generator.spec.mjs.snap @@ -304,7 +304,7 @@ Object { "path": "src/test/java/", "templates": Array [ Object { - "file": "package/ArchTest.java", + "file": "package/TechnicalStructureTest.java", "renameTo": [Function], }, ], diff --git a/generators/server/files.js b/generators/server/files.js index 361b16bddfc..aef11641ba9 100644 --- a/generators/server/files.js +++ b/generators/server/files.js @@ -761,8 +761,8 @@ const baseServerFiles = { path: SERVER_TEST_SRC_DIR, templates: [ { - file: 'package/ArchTest.java', - renameTo: generator => `${generator.testDir}ArchTest.java`, + file: 'package/TechnicalStructureTest.java', + renameTo: generator => `${generator.testDir}TechnicalStructureTest.java`, }, ], }, diff --git a/generators/server/templates/src/test/java/package/ArchTest.java.ejs b/generators/server/templates/src/test/java/package/ArchTest.java.ejs deleted file mode 100644 index 02ef98f0748..00000000000 --- a/generators/server/templates/src/test/java/package/ArchTest.java.ejs +++ /dev/null @@ -1,47 +0,0 @@ -<%# - Copyright 2013-2022 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>; - -import com.tngtech.archunit.core.domain.JavaClasses; -import com.tngtech.archunit.core.importer.ClassFileImporter; -import com.tngtech.archunit.core.importer.ImportOption; -import org.junit.jupiter.api.Test; - -import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; - -class ArchTest { - - @Test - void servicesAndRepositoriesShouldNotDependOnWebLayer() { - - JavaClasses importedClasses = new ClassFileImporter() - .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) - .importPackages("<%= packageName %>"); - - noClasses() - .that() - .resideInAnyPackage("<%= packageName %>.service..") - .or() - .resideInAnyPackage("<%= packageName %>.repository..") - .should().dependOnClassesThat() - .resideInAnyPackage("..<%= packageName %>.web..") - .because("Services and repositories should not depend on web layer") - .check(importedClasses); - } -} diff --git a/generators/server/templates/src/test/java/package/TechnicalStructureTest.java.ejs b/generators/server/templates/src/test/java/package/TechnicalStructureTest.java.ejs new file mode 100644 index 00000000000..02e9cccb922 --- /dev/null +++ b/generators/server/templates/src/test/java/package/TechnicalStructureTest.java.ejs @@ -0,0 +1,44 @@ +<%# + Copyright 2013-2022 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://www.jhipster.tech/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>; + +import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; + +import static com.tngtech.archunit.library.Architectures.layeredArchitecture; + +@AnalyzeClasses(packagesOf = <%= mainClass %>.class, importOptions = DoNotIncludeTests.class) +class TechnicalStructureTest { + + @ArchTest + static final ArchRule respectsTechnicalArchitectureLayers = layeredArchitecture() + .layer("Config").definedBy("..config..") + .layer("Web").definedBy("..web..") + .layer("Security").definedBy("..security..") + .layer("Service").definedBy("..service..") + .layer("Persistence").definedBy("..repository..") + .layer("Domain").definedBy("..domain..") + + .whereLayer("Web").mayNotBeAccessedByAnyLayer() + .whereLayer("Service").mayOnlyBeAccessedByLayers("Web", "Config") + .whereLayer("Persistence").mayOnlyBeAccessedByLayers("Service", "Security", "Web", "Config") + .whereLayer("Domain").mayOnlyBeAccessedByLayers("Persistence", "Service", "Security", "Web", "Config"); +} diff --git a/test/__snapshots__/app-client-custom-path.spec.js.snap b/test/__snapshots__/app-client-custom-path.spec.js.snap index cf0796fc69e..54c587b97ee 100644 --- a/test/__snapshots__/app-client-custom-path.spec.js.snap +++ b/test/__snapshots__/app-client-custom-path.spec.js.snap @@ -1223,10 +1223,10 @@ Object { "src/main/webapp2/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { diff --git a/test/__snapshots__/app.spec.js.snap b/test/__snapshots__/app.spec.js.snap index 1c149022f85..0e66c380158 100644 --- a/test/__snapshots__/app.spec.js.snap +++ b/test/__snapshots__/app.spec.js.snap @@ -362,10 +362,10 @@ Object { "src/main/resources/templates/mail/passwordResetEmail.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -799,10 +799,10 @@ Object { "src/main/resources/templates/mail/passwordResetEmail.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -3053,10 +3053,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -4393,10 +4393,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -5730,10 +5730,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -7061,10 +7061,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -8407,10 +8407,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -9774,10 +9774,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -10718,10 +10718,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -12067,10 +12067,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -13365,10 +13365,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -14681,10 +14681,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -16042,10 +16042,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { diff --git a/test/__snapshots__/server.spec.js.snap b/test/__snapshots__/server.spec.js.snap index 2e1f2e099d6..f5c2d885a61 100644 --- a/test/__snapshots__/server.spec.js.snap +++ b/test/__snapshots__/server.spec.js.snap @@ -437,10 +437,10 @@ Object { "src/main/webapp/i18n/fr/user-management.json": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { diff --git a/test/blueprint/__snapshots__/app-blueprint.spec.js.snap b/test/blueprint/__snapshots__/app-blueprint.spec.js.snap index 3329fbbaefd..1eeaf02f1c5 100644 --- a/test/blueprint/__snapshots__/app-blueprint.spec.js.snap +++ b/test/blueprint/__snapshots__/app-blueprint.spec.js.snap @@ -1223,10 +1223,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { @@ -2569,10 +2569,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object { diff --git a/test/blueprint/__snapshots__/scoped-blueprint.spec.js.snap b/test/blueprint/__snapshots__/scoped-blueprint.spec.js.snap index 6fa8f0b98cb..93cec22ba6b 100644 --- a/test/blueprint/__snapshots__/scoped-blueprint.spec.js.snap +++ b/test/blueprint/__snapshots__/scoped-blueprint.spec.js.snap @@ -1223,10 +1223,10 @@ Object { "src/main/webapp/swagger-ui/index.html": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/ArchTest.java": Object { + "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { "stateCleared": "modified", }, - "src/test/java/com/mycompany/myapp/IntegrationTest.java": Object { + "src/test/java/com/mycompany/myapp/TechnicalStructureTest.java": Object { "stateCleared": "modified", }, "src/test/java/com/mycompany/myapp/config/NoOpMailConfiguration.java": Object {