Repository: jhipster/jhipster-lite
Pull request #11799 (2025-01-26 20:51:18)

Tests: some refacto


Patch:
diff --git a/src/main/glyph/css/jhlite-icons-embedded.css b/src/main/glyph/css/jhlite-icons-embedded.css
index 52aaed896..e00b70350 100644
--- a/src/main/glyph/css/jhlite-icons-embedded.css
+++ b/src/main/glyph/css/jhlite-icons-embedded.css
@@ -28,7 +28,7 @@
 
 [class^='jhlite-icon-']:before,
 [class*=' jhlite-icon-']:before {
-  font-family: 'jhlite-icons', sans-serif;
+  font-family: 'jhlite-icons';
   font-style: normal;
   font-weight: normal;
   speak: never;
diff --git a/src/main/glyph/css/jhlite-icons-ie7.css b/src/main/glyph/css/jhlite-icons-ie7.css
index 3f9cb4979..88891dfb0 100644
--- a/src/main/glyph/css/jhlite-icons-ie7.css
+++ b/src/main/glyph/css/jhlite-icons-ie7.css
@@ -1,6 +1,6 @@
 [class^='jhlite-icon-'],
 [class*=' jhlite-icon-'] {
-  font-family: 'jhlite-icons', sans-serif;
+  font-family: 'jhlite-icons';
   font-style: normal;
   font-weight: normal;
 
diff --git a/src/main/glyph/css/jhlite-icons.css b/src/main/glyph/css/jhlite-icons.css
index d069244f6..14d92d11e 100644
--- a/src/main/glyph/css/jhlite-icons.css
+++ b/src/main/glyph/css/jhlite-icons.css
@@ -22,7 +22,7 @@
 */
 [class^='jhlite-icon-']:before,
 [class*=' jhlite-icon-']:before {
-  font-family: 'jhlite-icons', sans-serif;
+  font-family: 'jhlite-icons';
   font-style: normal;
   font-weight: normal;
   speak: never;
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/application/DatasourceApplicationService.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/application/DatasourceApplicationService.java
deleted file mode 100644
index f82e7767c..000000000
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/application/DatasourceApplicationService.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package tech.jhipster.lite.generator.server.springboot.database.datasource.application;
-
-import org.springframework.stereotype.Service;
-import tech.jhipster.lite.generator.server.springboot.database.datasource.domain.DatasourceModuleFactory;
-import tech.jhipster.lite.module.domain.JHipsterModule;
-import tech.jhipster.lite.module.domain.docker.DockerImages;
-import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
-
-@Service
-public class DatasourceApplicationService {
-
-  private final DatasourceModuleFactory factory;
-
-  public DatasourceApplicationService(DockerImages dockerImages) {
-    factory = new DatasourceModuleFactory(dockerImages);
-  }
-
-  public JHipsterModule buildPostgresql(JHipsterModuleProperties properties) {
-    return factory.buildPostgresql(properties);
-  }
-
-  public JHipsterModule buildMariaDB(JHipsterModuleProperties properties) {
-    return factory.buildMariaDB(properties);
-  }
-
-  public JHipsterModule buildMsSQL(JHipsterModuleProperties properties) {
-    return factory.buildMsSQL(properties);
-  }
-
-  public JHipsterModule buildMySQL(JHipsterModuleProperties properties) {
-    return factory.buildMySQL(properties);
-  }
-}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceModuleFactory.java
deleted file mode 100644
index 4efdc1f6c..000000000
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceModuleFactory.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package tech.jhipster.lite.generator.server.springboot.database.datasource.domain;
-
-import static tech.jhipster.lite.module.domain.JHipsterModule.artifactId;
-import static tech.jhipster.lite.module.domain.JHipsterModule.documentationTitle;
-import static tech.jhipster.lite.module.domain.JHipsterModule.from;
-import static tech.jhipster.lite.module.domain.JHipsterModule.groupId;
-import static tech.jhipster.lite.module.domain.JHipsterModule.javaDependency;
-import static tech.jhipster.lite.module.domain.JHipsterModule.lineBeforeText;
-import static tech.jhipster.lite.module.domain.JHipsterModule.moduleBuilder;
-import static tech.jhipster.lite.module.domain.JHipsterModule.path;
-import static tech.jhipster.lite.module.domain.JHipsterModule.propertyKey;
-import static tech.jhipster.lite.module.domain.JHipsterModule.propertyValue;
-import static tech.jhipster.lite.module.domain.JHipsterModule.to;
-import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcMainDocker;
-import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcTestJava;
-import static tech.jhipster.lite.module.domain.javadependency.JavaDependencyScope.RUNTIME;
-
-import java.util.function.Consumer;
-import tech.jhipster.lite.module.domain.JHipsterModule;
-import tech.jhipster.lite.module.domain.LogLevel;
-import tech.jhipster.lite.module.domain.docker.DockerImageName;
-import tech.jhipster.lite.module.domain.docker.DockerImageVersion;
-import tech.jhipster.lite.module.domain.docker.DockerImages;
-import tech.jhipster.lite.module.domain.file.JHipsterSource;
-import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
-import tech.jhipster.lite.shared.error.domain.Assert;
-
-public class DatasourceModuleFactory {
-
-  private static final String PROPERTIES = "properties";
-  private static final String ORG_POSTGRESQL = "org.postgresql";
-  private static final String POSTGRESQL = "postgresql";
-  private static final String MYSQL = "mysql";
-  private static final String MARIADB = "mariadb";
-
-  private static final String SPRING_DATASOURCE_URL = "spring.datasource.url";
-  private static final String SPRING_DATASOURCE_USERNAME = "spring.datasource.username";
-  private static final String SPRING_DATASOURCE_PASSWORD = "spring.datasource.password";
-  private static final String SPRING_DATASOURCE_DRIVER_CLASS_NAME = "spring.datasource.driver-class-name";
-
-  private static final JHipsterSource SOURCE = from("server/springboot/database/datasource");
-
-  private final DockerImages dockerImages;
-
-  public DatasourceModuleFactory(DockerImages dockerImages) {
-    this.dockerImages = dockerImages;
-  }
-
-  public JHipsterModule buildPostgresql(JHipsterModuleProperties properties) {
-    Assert.notNull(PROPERTIES, properties);
-
-    DatasourceProperties datasourceProperties = DatasourceProperties.builder()
-      .id(POSTGRESQL)
-      .databaseName("PostgreSQL")
-      .driverDependency(javaDependency().groupId(ORG_POSTGRESQL).artifactId(POSTGRESQL).scope(RUNTIME).build())
-      .driverClassName("org.postgresql.Driver")
-      .dockerImageName(new DockerImageName("postgres"))
-      .testContainerArtifactId(artifactId(POSTGRESQL));
-
-    DockerImageVersion dockerImage = dockerImages.get(datasourceProperties.dockerImageName());
-
-    //@formatter:off
-    return moduleBuilder(properties)
-      .apply(dockerContainer(dockerImages, datasourceProperties))
-      .apply(connectionPool(datasourceProperties))
-      .apply(testcontainers(dockerImages, properties, datasourceProperties))
-      .springMainProperties()
-        .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:postgresql://localhost:5432/" + properties.projectBaseName().name()))
-        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue(properties.projectBaseName().name()))
-        .and()
-      .springTestProperties()
-        .set(
-          propertyKey(SPRING_DATASOURCE_URL),
-          propertyValue(
-            "jdbc:tc:postgresql:" + dockerImage.version().get() + ":///" + properties.projectBaseName().name() + "?TC_TMPFS=/testtmpfs:rw"
-          )
-        )
-        .and()
-      .springMainLogger(ORG_POSTGRESQL, LogLevel.WARN)
-      .springTestLogger(ORG_POSTGRESQL, LogLevel.WARN)
-      .springTestLogger("org.jboss.logging", LogLevel.WARN)
-      .build();
-    //@formatter:on
-  }
-
-  public JHipsterModule buildMariaDB(JHipsterModuleProperties properties) {
-    Assert.notNull(PROPERTIES, properties);
-
-    DatasourceProperties datasourceProperties = DatasourceProperties.builder()
-      .id(MARIADB)
-      .databaseName("MariaDB")
-      .driverDependency(javaDependency().groupId("org.mariadb.jdbc").artifactId("mariadb-java-client").scope(RUNTIME).build())
-      .driverClassName("org.mariadb.jdbc.Driver")
-      .dockerImageName(new DockerImageName(MARIADB))
-      .testContainerArtifactId(artifactId(MARIADB));
-
-    //@formatter:off
-    return moduleBuilder(properties)
-      .apply(dockerContainer(dockerImages, datasourceProperties))
-      .apply(connectionPool( datasourceProperties))
-      .apply(testcontainers(dockerImages,  properties, datasourceProperties))
-      .springMainProperties()
-        .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:mariadb://localhost:3306/" + properties.projectBaseName().name()))
-        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("root"))
-        .and()
-      .build();
-    //@formatter:on
-  }
-
-  public JHipsterModule buildMySQL(JHipsterModuleProperties properties) {
-    Assert.notNull(PROPERTIES, properties);
-
-    DatasourceProperties datasourceProperties = DatasourceProperties.builder()
-      .id(MYSQL)
-      .databaseName("MySQL")
-      .driverDependency(javaDependency().groupId("com.mysql").artifactId("mysql-connector-j").scope(RUNTIME).build())
-      .driverClassName("com.mysql.cj.jdbc.Driver")
-      .dockerImageName(new DockerImageName(MYSQL))
-      .testContainerArtifactId(artifactId(MYSQL));
-
-    //@formatter:off
-    return moduleBuilder(properties)
-      .apply(dockerContainer(dockerImages, datasourceProperties))
-      .apply(connectionPool( datasourceProperties))
-      .apply(testcontainers(dockerImages,  properties, datasourceProperties))
-      .springMainProperties()
-        .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:mysql://localhost:3306/" + properties.projectBaseName().name()))
-        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("root"))
-        .and()
-      .build();
-    //@formatter:on
-  }
-
-  public JHipsterModule buildMsSQL(JHipsterModuleProperties properties) {
-    Assert.notNull(PROPERTIES, properties);
-
-    DatasourceProperties datasourceProperties = DatasourceProperties.builder()
-      .id("mssql")
-      .databaseName("MsSQL")
-      .driverDependency(javaDependency().groupId("com.microsoft.sqlserver").artifactId("mssql-jdbc").scope(RUNTIME).build())
-      .driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
-      .dockerImageName(new DockerImageName("mcr.microsoft.com/mssql/server"))
-      .testContainerArtifactId(artifactId("mssqlserver"));
-
-    //@formatter:off
-    return moduleBuilder(properties)
-      .apply(dockerContainer(dockerImages, datasourceProperties))
-      .apply(connectionPool(datasourceProperties))
-      .apply(testcontainers(dockerImages,  properties, datasourceProperties))
-      .files()
-        .add(SOURCE.append("docker").template("container-license-acceptance.txt"), to("src/test/resources/container-license-acceptance.txt"))
-        .add(
-          SOURCE.template("MsSQLTestContainerExtension.java"),
-          toSrcTestJava().append(properties.basePackage().path()).append("MsSQLTestContainerExtension.java")
-        )
-        .and()
-      .springMainProperties()
-        .set(
-          propertyKey(SPRING_DATASOURCE_URL),
-          propertyValue("jdbc:sqlserver://localhost:1433;database=" + properties.projectBaseName().name() + ";trustServerCertificate=true")
-        )
-        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("SA"))
-        .set(propertyKey(SPRING_DATASOURCE_PASSWORD), propertyValue("yourStrong(!)Password"))
-        .and()
-      .springTestProperties()
-        .set(
-          propertyKey(SPRING_DATASOURCE_URL),
-          propertyValue(
-            "jdbc:tc:sqlserver:///;database=" + properties.projectBaseName().name() + ";trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw"
-          )
-        )
-        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("SA"))
-        .set(propertyKey(SPRING_DATASOURCE_PASSWORD), propertyValue("yourStrong(!)Password"))
-        .and()
-      .mandatoryReplacements()
-        .in(path("src/test/java").append(properties.basePackage().path()).append("IntegrationTest.java"))
-          .add(
-            lineBeforeText("import org.springframework.boot.test.context.SpringBootTest;"),
-            "import org.junit.jupiter.api.extension.ExtendWith;"
-          )
-          .add(lineBeforeText("public @interface"), "@ExtendWith(MsSQLTestContainerExtension.class)")
-          .and()
-        .and()
-      .springMainLogger("com.microsoft.sqlserver", LogLevel.WARN)
-      .springMainLogger("org.reflections", LogLevel.WARN)
-      .build();
-    //@formatter:on
-  }
-
-  public static Consumer<JHipsterModule.JHipsterModuleBuilder> dockerContainer(
-    DockerImages dockerImages,
-    DatasourceProperties datasourceProperties
-  ) {
-    DockerImageVersion dockerImage = dockerImages.get(datasourceProperties.dockerImageName());
-
-    //@formatter:off
-    return moduleBuilder ->
-      moduleBuilder
-        .context()
-          .put("srcMainDocker", "src/main/docker")
-          .put("databaseType", datasourceProperties.id())
-          .put(datasourceProperties.id() + "DockerImageWithVersion", dockerImage.fullName())
-          .and()
-        .documentation(documentationTitle(datasourceProperties.databaseName()), SOURCE.template("databaseType.md"))
-        .startupCommands()
-          .dockerCompose("src/main/docker/" + datasourceProperties.id() + ".yml")
-          .and()
-        .files()
-          .add(SOURCE.append("docker").template(datasourceProperties.id() + ".yml"), toSrcMainDocker().append(datasourceProperties.id() + ".yml"));
-  }
-
-  public static Consumer<JHipsterModule.JHipsterModuleBuilder> testcontainers(DockerImages dockerImages, JHipsterModuleProperties moduleProperties, DatasourceProperties datasourceProperties) {
-    DockerImageVersion dockerImage = dockerImages.get(datasourceProperties.dockerImageName());
-
-    //@formatter:off
-    return moduleBuilder ->
-      moduleBuilder
-        .javaDependencies()
-        .addDependency(datasourceProperties.testContainerDependency())
-        .and()
-        .springTestProperties()
-        .set(
-          propertyKey(SPRING_DATASOURCE_URL),
-          propertyValue("jdbc:tc:" + dockerImage.fullName() + ":///" + moduleProperties.projectBaseName().name())
-        )
-        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue(moduleProperties.projectBaseName().name()))
-        .set(propertyKey(SPRING_DATASOURCE_PASSWORD), propertyValue(""))
-        .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("org.testcontainers.jdbc.ContainerDatabaseDriver"))
-        .and()
-        .springTestLogger("com.github.dockerjava", LogLevel.WARN)
-        .springTestLogger("org.testcontainers", LogLevel.WARN);
-  }
-
-  public static Consumer<JHipsterModule.JHipsterModuleBuilder> connectionPool(DatasourceProperties datasourceProperties) {
-    //@formatter:off
-    return moduleBuilder ->
-      moduleBuilder
-        .javaDependencies()
-          .addDependency(datasourceProperties.driverDependency())
-          .addDependency(groupId("com.zaxxer"), artifactId("HikariCP"))
-          .and()
-        .springMainProperties()
-          .set(propertyKey(SPRING_DATASOURCE_PASSWORD), propertyValue(""))
-          .set(propertyKey("spring.datasource.type"), propertyValue("com.zaxxer.hikari.HikariDataSource"))
-          .set(propertyKey("spring.datasource.hikari.poolName"), propertyValue("Hikari"))
-          .set(propertyKey("spring.datasource.hikari.auto-commit"), propertyValue(false))
-          .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue(datasourceProperties.driverClassName()))
-          .and()
-        .springTestProperties()
-          .set(propertyKey("spring.datasource.hikari.maximum-pool-size"), propertyValue(2));
-  }
-}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceProperties.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceProperties.java
deleted file mode 100644
index b25466821..000000000
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceProperties.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package tech.jhipster.lite.generator.server.springboot.database.datasource.domain;
-
-import static tech.jhipster.lite.module.domain.JHipsterModule.javaDependency;
-
-import tech.jhipster.lite.module.domain.docker.DockerImageName;
-import tech.jhipster.lite.module.domain.javabuild.ArtifactId;
-import tech.jhipster.lite.module.domain.javadependency.JavaDependency;
-import tech.jhipster.lite.module.domain.javadependency.JavaDependencyScope;
-
-public final class DatasourceProperties {
-
-  private final String id;
-  private final String databaseName;
-  private final JavaDependency driverDependency;
-  private final String driverClassName;
-  private final DockerImageName dockerImageName;
-  private final ArtifactId testContainerArtifactId;
-
-  private DatasourceProperties(DatasourcePropertiesBuilder builder) {
-    this.id = builder.id;
-    this.databaseName = builder.databaseName;
-    this.driverDependency = builder.driverDependency;
-    this.driverClassName = builder.driverClassName;
-    this.dockerImageName = builder.dockerImageName;
-    this.testContainerArtifactId = builder.testContainerArtifactId;
-  }
-
-  public static DatasourcePropertiesIdBuilder builder() {
-    return new DatasourcePropertiesBuilder();
-  }
-
-  public String id() {
-    return id;
-  }
-
-  public String databaseName() {
-    return databaseName;
-  }
-
-  public JavaDependency driverDependency() {
-    return driverDependency;
-  }
-
-  public String driverClassName() {
-    return driverClassName;
-  }
-
-  public DockerImageName dockerImageName() {
-    return dockerImageName;
-  }
-
-  public JavaDependency testContainerDependency() {
-    return javaDependency()
-      .groupId("org.testcontainers")
-      .artifactId(testContainerArtifactId)
-      .dependencySlug("%s-%s".formatted("testcontainers", testContainerArtifactId))
-      .versionSlug("testcontainers")
-      .scope(JavaDependencyScope.TEST)
-      .build();
-  }
-
-  public sealed interface DatasourcePropertiesIdBuilder permits DatasourcePropertiesBuilder {
-    DatasourcePropertiesDatabaseNameBuilder id(String id);
-  }
-
-  public sealed interface DatasourcePropertiesDatabaseNameBuilder permits DatasourcePropertiesBuilder {
-    DatasourcePropertiesDriverDependencyBuilder databaseName(String databaseName);
-  }
-
-  public sealed interface DatasourcePropertiesDriverDependencyBuilder permits DatasourcePropertiesBuilder {
-    DatasourcePropertiesDriverClassNameBuilder driverDependency(JavaDependency driverDependency);
-  }
-
-  public sealed interface DatasourcePropertiesDriverClassNameBuilder permits DatasourcePropertiesBuilder {
-    DatasourcePropertiesDockerImageNameBuilder driverClassName(String driverClassName);
-  }
-
-  public sealed interface DatasourcePropertiesDockerImageNameBuilder permits DatasourcePropertiesBuilder {
-    DatasourcePropertiesTestContainerArtifactIdBuilder dockerImageName(DockerImageName dockerImageName);
-  }
-
-  public sealed interface DatasourcePropertiesTestContainerArtifactIdBuilder permits DatasourcePropertiesBuilder {
-    DatasourceProperties testContainerArtifactId(ArtifactId testContainerArtifactId);
-  }
-
-  private static final class DatasourcePropertiesBuilder
-    implements
-      DatasourcePropertiesIdBuilder,
-      DatasourcePropertiesDatabaseNameBuilder,
-      DatasourcePropertiesDriverDependencyBuilder,
-      DatasourcePropertiesDriverClassNameBuilder,
-      DatasourcePropertiesDockerImageNameBuilder,
-      DatasourcePropertiesTestContainerArtifactIdBuilder {
-
-    private String id;
-    private String databaseName;
-    private JavaDependency driverDependency;
-    private String driverClassName;
-    private DockerImageName dockerImageName;
-    private ArtifactId testContainerArtifactId;
-
-    @Override
-    public DatasourcePropertiesDatabaseNameBuilder id(String id) {
-      this.id = id;
-
-      return this;
-    }
-
-    @Override
-    public DatasourcePropertiesDriverDependencyBuilder databaseName(String databaseName) {
-      this.databaseName = databaseName;
-
-      return this;
-    }
-
-    @Override
-    public DatasourcePropertiesDriverClassNameBuilder driverDependency(JavaDependency driverDependency) {
-      this.driverDependency = driverDependency;
-
-      return this;
-    }
-
-    @Override
-    public DatasourcePropertiesDockerImageNameBuilder driverClassName(String driverClassName) {
-      this.driverClassName = driverClassName;
-
-      return this;
-    }
-
-    @Override
-    public DatasourcePropertiesTestContainerArtifactIdBuilder dockerImageName(DockerImageName dockerImageName) {
-      this.dockerImageName = dockerImageName;
-
-      return this;
-    }
-
-    @Override
-    public DatasourceProperties testContainerArtifactId(ArtifactId testContainerArtifactId) {
-      this.testContainerArtifactId = testContainerArtifactId;
-
-      return new DatasourceProperties(this);
-    }
-  }
-}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/infrastructure/primary/DatasourceModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/infrastructure/primary/DatasourceModuleConfiguration.java
deleted file mode 100644
index 1e1f7ed8d..000000000
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/infrastructure/primary/DatasourceModuleConfiguration.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package tech.jhipster.lite.generator.server.springboot.database.datasource.infrastructure.primary;
-
-import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.DATASOURCE;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MARIADB;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MSSQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MYSQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_POSTGRESQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.SPRING_BOOT;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import tech.jhipster.lite.generator.server.springboot.database.datasource.application.DatasourceApplicationService;
-import tech.jhipster.lite.module.domain.resource.JHipsterModuleOrganization;
-import tech.jhipster.lite.module.domain.resource.JHipsterModulePropertiesDefinition;
-import tech.jhipster.lite.module.domain.resource.JHipsterModuleResource;
-
-@Configuration
-class DatasourceModuleConfiguration {
-
-  private static final String API_DOC_GROUP = "Spring Boot - Database";
-
-  @Bean
-  JHipsterModuleResource postgresqlDatasourceModule(DatasourceApplicationService datasource) {
-    return JHipsterModuleResource.builder()
-      .slug(DATASOURCE_POSTGRESQL)
-      .propertiesDefinition(properties())
-      .apiDoc(API_DOC_GROUP, "Add Postgresql datasource to Spring project")
-      .organization(organization())
-      .tags(tags())
-      .factory(datasource::buildPostgresql);
-  }
-
-  @Bean
-  JHipsterModuleResource mariaDBDatasourceModule(DatasourceApplicationService datasource) {
-    return JHipsterModuleResource.builder()
-      .slug(DATASOURCE_MARIADB)
-      .propertiesDefinition(properties())
-      .apiDoc(API_DOC_GROUP, "Add MariaDB datasource to Spring project")
-      .organization(organization())
-      .tags(tags())
-      .factory(datasource::buildMariaDB);
-  }
-
-  @Bean
-  JHipsterModuleResource mmySQLDatasourceModule(DatasourceApplicationService datasource) {
-    return JHipsterModuleResource.builder()
-      .slug(DATASOURCE_MYSQL)
-      .propertiesDefinition(properties())
-      .apiDoc(API_DOC_GROUP, "Add MySQL datasource to Spring project")
-      .organization(organization())
-      .tags(tags())
-      .factory(datasource::buildMySQL);
-  }
-
-  @Bean
-  JHipsterModuleResource msSQLDatasourceModule(DatasourceApplicationService datasource) {
-    return JHipsterModuleResource.builder()
-      .slug(DATASOURCE_MSSQL)
-      .propertiesDefinition(properties())
-      .apiDoc(API_DOC_GROUP, "Add MsSQL datasource to Spring project")
-      .organization(organization())
-      .tags(tags())
-      .factory(datasource::buildMsSQL);
-  }
-
-  private static JHipsterModulePropertiesDefinition properties() {
-    return JHipsterModulePropertiesDefinition.builder().addIndentation().addProjectBaseName().addSpringConfigurationFormat().build();
-  }
-
-  private static JHipsterModuleOrganization organization() {
-    return JHipsterModuleOrganization.builder().feature(DATASOURCE).addDependency(SPRING_BOOT).build();
-  }
-
-  private static String[] tags() {
-    return new String[] { "server", "spring", "spring-boot", "datasource", "database" };
-  }
-}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/package-info.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/package-info.java
deleted file mode 100644
index 1f1015546..000000000
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/datasource/package-info.java
+++ /dev/null
@@ -1,2 +0,0 @@
-@tech.jhipster.lite.BusinessContext
-package tech.jhipster.lite.generator.server.springboot.database.datasource;
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/application/JooqApplicationService.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/application/JooqApplicationService.java
index e47b496de..05c7455ad 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/application/JooqApplicationService.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/application/JooqApplicationService.java
@@ -3,6 +3,7 @@ package tech.jhipster.lite.generator.server.springboot.database.jooq.application
 import org.springframework.stereotype.Service;
 import tech.jhipster.lite.generator.server.springboot.database.jooq.domain.JooqModuleFactory;
 import tech.jhipster.lite.module.domain.JHipsterModule;
+import tech.jhipster.lite.module.domain.docker.DockerImages;
 import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
 
 @Service
@@ -10,8 +11,8 @@ public class JooqApplicationService {
 
   private final JooqModuleFactory factory;
 
-  public JooqApplicationService() {
-    factory = new JooqModuleFactory();
+  public JooqApplicationService(DockerImages dockerImages) {
+    factory = new JooqModuleFactory(dockerImages);
   }
 
   public JHipsterModule buildPostgresql(JHipsterModuleProperties properties) {
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/CommonModuleBuilder.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/CommonModuleBuilder.java
new file mode 100644
index 000000000..a6fbf7f82
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/CommonModuleBuilder.java
@@ -0,0 +1,89 @@
+package tech.jhipster.lite.generator.server.springboot.database.jooq.domain;
+
+import static tech.jhipster.lite.module.domain.JHipsterModule.*;
+
+import tech.jhipster.lite.module.domain.DocumentationTitle;
+import tech.jhipster.lite.module.domain.JHipsterModule;
+import tech.jhipster.lite.module.domain.docker.DockerImageVersion;
+import tech.jhipster.lite.module.domain.file.JHipsterSource;
+import tech.jhipster.lite.module.domain.javabuild.ArtifactId;
+import tech.jhipster.lite.module.domain.javadependency.JavaDependency;
+import tech.jhipster.lite.module.domain.javadependency.JavaDependencyScope;
+import tech.jhipster.lite.module.domain.javaproperties.PropertyValue;
+import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
+import tech.jhipster.lite.shared.error.domain.Assert;
+
+final class CommonModuleBuilder {
+
+  private static final PropertyValue FALSE = propertyValue(false);
+
+  private CommonModuleBuilder() {}
+
+  public static JHipsterModule.JHipsterModuleBuilder commonModuleBuilder(
+    JHipsterModuleProperties properties,
+    DatabaseType databaseType,
+    DockerImageVersion dockerImage,
+    DocumentationTitle documentationTitle,
+    ArtifactId testContainerArtifactId
+  ) {
+    Assert.notNull("properties", properties);
+    Assert.notNull("databaseType", databaseType);
+    Assert.notNull("dockerImage", dockerImage);
+    Assert.notNull("documentationTitle", documentationTitle);
+    Assert.notNull("testContainerArtifactId", testContainerArtifactId);
+
+    String databaseId = databaseType.id();
+    JHipsterSource source = from("server/springboot/database/common");
+
+    //@formatter:off
+    return moduleBuilder(properties)
+      .context()
+      .put("srcMainDocker", "src/main/docker") // To be used in <databaseId>>.md file
+      .put("databaseType", databaseId)
+      .put(databaseId + "DockerImageWithVersion", dockerImage.fullName()) // To be used in <databaseId>.yml docker-compose file
+      .and()
+      .documentation(documentationTitle, source.template("databaseType.md"))
+      .startupCommands()
+      .dockerCompose(startupCommand(databaseId))
+      .and()
+      .files()
+      .add(source.append("docker").template(databaseId + ".yml"), toSrcMainDocker().append(databaseId + ".yml"))
+      .and()
+      .javaDependencies()
+      .addDependency(groupId("org.springframework.boot"), artifactId("spring-boot-starter-jooq"))
+      .addDependency(groupId("com.zaxxer"), artifactId("HikariCP"))
+      .addDependency(testContainer(testContainerArtifactId))
+      .and()
+      .springMainProperties()
+      .set(propertyKey("spring.datasource.password"), propertyValue(""))
+      .set(propertyKey("spring.datasource.type"), propertyValue("com.zaxxer.hikari.HikariDataSource"))
+      .set(propertyKey("spring.datasource.hikari.poolName"), propertyValue("Hikari"))
+      .set(propertyKey("spring.datasource.hikari.auto-commit"), FALSE)
+      .and()
+      .springTestProperties()
+      .set(
+        propertyKey("spring.datasource.url"),
+        propertyValue("jdbc:tc:" + dockerImage.fullName() + ":///" + properties.projectBaseName().name())
+      )
+      .set(propertyKey("spring.datasource.username"), propertyValue(properties.projectBaseName().name()))
+      .set(propertyKey("spring.datasource.password"), propertyValue(""))
+      .set(propertyKey("spring.datasource.driver-class-name"), propertyValue("org.testcontainers.jdbc.ContainerDatabaseDriver"))
+      .set(propertyKey("spring.datasource.hikari.maximum-pool-size"), propertyValue(2))
+      .and();
+    //@formatter:on
+  }
+
+  private static String startupCommand(String databaseId) {
+    return "src/main/docker/" + databaseId + ".yml";
+  }
+
+  private static JavaDependency testContainer(ArtifactId testContainerArtifactId) {
+    return javaDependency()
+      .groupId("org.testcontainers")
+      .artifactId(testContainerArtifactId)
+      .dependencySlug("%s-%s".formatted("testcontainers", testContainerArtifactId))
+      .versionSlug("testcontainers")
+      .scope(JavaDependencyScope.TEST)
+      .build();
+  }
+}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/DatabaseType.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/DatabaseType.java
new file mode 100644
index 000000000..8feebc291
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/DatabaseType.java
@@ -0,0 +1,18 @@
+package tech.jhipster.lite.generator.server.springboot.database.jooq.domain;
+
+enum DatabaseType {
+  POSTGRESQL("postgresql"),
+  MYSQL("mysql"),
+  MARIADB("mariadb"),
+  MSSQL("mssql");
+
+  private final String id;
+
+  DatabaseType(String id) {
+    this.id = id;
+  }
+
+  public String id() {
+    return id;
+  }
+}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleFactory.java
index 758de61dc..e5c4cd550 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleFactory.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleFactory.java
@@ -1,116 +1,238 @@
 package tech.jhipster.lite.generator.server.springboot.database.jooq.domain;
 
-import static tech.jhipster.lite.module.domain.JHipsterModule.artifactId;
-import static tech.jhipster.lite.module.domain.JHipsterModule.groupId;
-import static tech.jhipster.lite.module.domain.JHipsterModule.mavenPlugin;
-import static tech.jhipster.lite.module.domain.JHipsterModule.moduleBuilder;
-import static tech.jhipster.lite.module.domain.JHipsterModule.pluginExecution;
-import static tech.jhipster.lite.module.domain.mavenplugin.MavenBuildPhase.GENERATE_RESOURCES;
+import static tech.jhipster.lite.generator.server.springboot.database.jooq.domain.CommonModuleBuilder.commonModuleBuilder;
+import static tech.jhipster.lite.module.domain.JHipsterModule.*;
+import static tech.jhipster.lite.module.domain.JHipsterModule.lineBeforeText;
 
 import tech.jhipster.lite.module.domain.JHipsterModule;
-import tech.jhipster.lite.module.domain.mavenplugin.MavenPlugin;
+import tech.jhipster.lite.module.domain.LogLevel;
+import tech.jhipster.lite.module.domain.docker.DockerImageVersion;
+import tech.jhipster.lite.module.domain.docker.DockerImages;
+import tech.jhipster.lite.module.domain.file.JHipsterSource;
+import tech.jhipster.lite.module.domain.javadependency.JavaDependency;
+import tech.jhipster.lite.module.domain.javadependency.JavaDependencyScope;
+import tech.jhipster.lite.module.domain.mavenplugin.MavenBuildPhase;
 import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
-import tech.jhipster.lite.shared.error.domain.Assert;
 
 public class JooqModuleFactory {
 
+  public static final String GENERATE = "generate";
+  public static final String JOOQ_CODEGEN = "jooq-codegen";
+  public static final String JOOQ_CODEGEN_MAVEN = "jooq-codegen-maven";
+  public static final String ORG_JOOQ = "org.jooq";
+  public static final String MSSQL_PASSWORD = "yourStrong(!)Password";
+  public static final String ORG_POSTGRESQL = "org.postgresql";
+  private static final String MYSQL = "mysql";
+  private static final String MYSQL_GROUP_ID = "com.mysql";
+  private static final String MYSQL_ARTIFACT_ID = "mysql-connector-j";
+
+  private static final String SPRING_DATASOURCE_URL = "spring.datasource.url";
+  private static final String SPRING_DATASOURCE_USERNAME = "spring.datasource.username";
+  private static final String SPRING_DATASOURCE_DRIVER_CLASS_NAME = "spring.datasource.driver-class-name";
+
+  private final DockerImages dockerImages;
+
+  public JooqModuleFactory(DockerImages dockerImages) {
+    this.dockerImages = dockerImages;
+  }
+
   public JHipsterModule buildPostgresql(JHipsterModuleProperties properties) {
+    DockerImageVersion dockerImage = dockerImages.get("postgres");
+
     //@formatter:off
-    return commonModuleBuilder(properties)
+    return commonModuleBuilder(
+      properties,
+      DatabaseType.POSTGRESQL,
+      dockerImage,
+      documentationTitle("Postgresql"),
+      artifactId("postgresql")
+    )
+      .javaDependencies()
+      .addDependency(
+        JavaDependency.builder()
+          .groupId(groupId(ORG_POSTGRESQL))
+          .artifactId(artifactId("postgresql"))
+          .scope(JavaDependencyScope.RUNTIME)
+          .build()
+      )
+      .and()
       .mavenPlugins()
-        .plugin(jooqMavenCodegenPlugin(postgresqlPluginConfiguration(properties)))
-        .and()
+        .plugin(mavenPlugin()
+          .groupId(ORG_JOOQ)
+          .artifactId(JOOQ_CODEGEN_MAVEN)
+          .versionSlug("jooq")
+          .addExecution(pluginExecution().goals(GENERATE).id(JOOQ_CODEGEN).phase(MavenBuildPhase.GENERATE_RESOURCES))
+          .configuration(jooqModuleCodegenConfiguration()
+            .database(tech.jhipster.lite.module.domain.jooqplugin.DatabaseType.POSTGRESQL)
+            .databaseUrl("jdbc:postgresql://localhost:5432/" + properties.projectBaseName().name())
+            .user(properties.projectBaseName().name())
+            .inputSchema("public")
+            .build()
+            .getConfiguration())
+          .build())
+      .and()
+      .springMainProperties()
+      .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:postgresql://localhost:5432/" + properties.projectBaseName().name()))
+      .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue(properties.projectBaseName().name()))
+      .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("org.postgresql.Driver"))
+      .and()
+      .springTestProperties()
+      .set(
+        propertyKey(SPRING_DATASOURCE_URL),
+        propertyValue(
+          "jdbc:tc:postgresql:" + dockerImage.version().get() + ":///" + properties.projectBaseName().name() + "?TC_TMPFS=/testtmpfs:rw"
+        )
+      )
+      .and()
+      .springMainLogger(ORG_POSTGRESQL, LogLevel.WARN)
+      .springTestLogger(ORG_POSTGRESQL, LogLevel.WARN)
+      .springTestLogger("org.jboss.logging", LogLevel.WARN)
       .build();
     //@formatter:on
   }
 
-  private static String postgresqlPluginConfiguration(JHipsterModuleProperties properties) {
-    return JooqModuleCodegenConfiguration.builder()
-      .databaseUrl("jdbc:postgresql://localhost:5432/" + properties.projectBaseName().name())
-      .user(properties.projectBaseName().name())
-      .inputSchema("public")
-      .jooqMetaDatabase("org.jooq.meta.postgres.PostgresDatabase")
-      .build()
-      .getConfiguration();
-  }
-
   public JHipsterModule buildMariaDB(JHipsterModuleProperties properties) {
     //@formatter:off
-    return commonModuleBuilder(properties)
+    return commonModuleBuilder(
+      properties,
+      DatabaseType.MARIADB,
+      dockerImages.get("mariadb"),
+      documentationTitle("MariaDB"),
+      artifactId("mariadb")
+    )
+      .javaDependencies()
+      .addDependency(
+        javaDependency().groupId("org.mariadb.jdbc").artifactId("mariadb-java-client").scope(JavaDependencyScope.RUNTIME).build()
+      )
+      .and()
       .mavenPlugins()
-        .plugin(jooqMavenCodegenPlugin(mariadbPluginConfiguration(properties)))
-        .and()
+      .plugin(mavenPlugin()
+        .groupId(ORG_JOOQ)
+        .artifactId(JOOQ_CODEGEN_MAVEN)
+        .versionSlug("jooq")
+        .addExecution(pluginExecution().goals(GENERATE).id(JOOQ_CODEGEN).phase(MavenBuildPhase.GENERATE_RESOURCES))
+        .configuration(jooqModuleCodegenConfiguration()
+          .database(tech.jhipster.lite.module.domain.jooqplugin.DatabaseType.MARIADB)
+          .databaseUrl("jdbc:mariadb://localhost:3306/" + properties.projectBaseName().name())
+            .user("root")
+            .inputSchema("properties.projectBaseName().name()")
+            .build()
+            .getConfiguration())
+        .build())
+      .and()
+      .springMainProperties()
+      .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:mariadb://localhost:3306/" + properties.projectBaseName().name()))
+      .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("root"))
+      .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("org.mariadb.jdbc.Driver"))
+      .and()
       .build();
     //@formatter:on
   }
 
-  private static String mariadbPluginConfiguration(JHipsterModuleProperties properties) {
-    return JooqModuleCodegenConfiguration.builder()
-      .databaseUrl("jdbc:mariadb://localhost:3306/" + properties.projectBaseName().name())
-      .user("root")
-      .inputSchema(properties.projectBaseName().name())
-      .jooqMetaDatabase("org.jooq.meta.mariadb.MariaDBDatabase")
-      .build()
-      .getConfiguration();
-  }
-
   public JHipsterModule buildMySQL(JHipsterModuleProperties properties) {
     //@formatter:off
-    return commonModuleBuilder(properties)
+    return commonModuleBuilder(
+      properties,
+      DatabaseType.MYSQL,
+      dockerImages.get(MYSQL),
+      documentationTitle("MySQL"),
+      artifactId(MYSQL)
+    )
+      .javaDependencies()
+      .addDependency(javaDependency().groupId(MYSQL_GROUP_ID).artifactId(MYSQL_ARTIFACT_ID).scope(JavaDependencyScope.RUNTIME).build())
+      .and()
       .mavenPlugins()
-        .plugin(jooqMavenCodegenPlugin(mysqlPluginConfiguration(properties)))
-        .and()
+      .plugin(mavenPlugin()
+        .groupId(ORG_JOOQ)
+        .artifactId(JOOQ_CODEGEN_MAVEN)
+        .versionSlug("jooq")
+        .addExecution(pluginExecution().goals(GENERATE).id(JOOQ_CODEGEN).phase(MavenBuildPhase.GENERATE_RESOURCES))
+        .configuration(jooqModuleCodegenConfiguration()
+          .database(tech.jhipster.lite.module.domain.jooqplugin.DatabaseType.MYSQL)
+          .databaseUrl("jdbc:mysql://localhost:3306/" + properties.projectBaseName().name())
+          .user("root")
+          .inputSchema("properties.projectBaseName().name()")
+          .build()
+          .getConfiguration())
+        .build())
+      .and()
+      .springMainProperties()
+      .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:mysql://localhost:3306/" + properties.projectBaseName().name()))
+      .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("root"))
+      .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("com.mysql.cj.jdbc.Driver"))
+      .and()
       .build();
     //@formatter:on
   }
 
-  private static String mysqlPluginConfiguration(JHipsterModuleProperties properties) {
-    return JooqModuleCodegenConfiguration.builder()
-      .databaseUrl("jdbc:mysql://localhost:3306/" + properties.projectBaseName().name())
-      .user("root")
-      .inputSchema(properties.projectBaseName().name())
-      .jooqMetaDatabase("org.jooq.meta.mysql.MySQLDatabase")
-      .build()
-      .getConfiguration();
-  }
-
   public JHipsterModule buildMsSQL(JHipsterModuleProperties properties) {
+    DockerImageVersion dockerImage = dockerImages.get("mcr.microsoft.com/mssql/server");
+    JHipsterSource source = from("server/springboot/database/common");
+
     //@formatter:off
-    return commonModuleBuilder(properties)
+    return commonModuleBuilder(
+      properties,
+      DatabaseType.MSSQL,
+      dockerImage,
+      documentationTitle("MsSQL"),
+      artifactId("mssqlserver")
+    )
+      .files()
+      .add(source.append("docker").template("container-license-acceptance.txt"), to("src/test/resources/container-license-acceptance.txt"))
+      .add(
+        source.template("MsSQLTestContainerExtension.java"),
+        toSrcTestJava().append(properties.basePackage().path()).append("MsSQLTestContainerExtension.java")
+      )
+      .and()
+      .javaDependencies()
+      .addDependency(javaDependency().groupId("com.microsoft.sqlserver").artifactId("mssql-jdbc").scope(JavaDependencyScope.RUNTIME).build())
+      .and()
       .mavenPlugins()
-        .plugin(jooqMavenCodegenPlugin(mssqlPluginConfiguration(properties)))
-        .and()
+      .plugin(mavenPlugin()
+        .groupId(ORG_JOOQ)
+        .artifactId(JOOQ_CODEGEN_MAVEN)
+        .versionSlug("jooq")
+        .addExecution(pluginExecution().goals(GENERATE).id(JOOQ_CODEGEN).phase(MavenBuildPhase.GENERATE_RESOURCES))
+        .configuration(jooqModuleCodegenConfiguration()
+          .database(tech.jhipster.lite.module.domain.jooqplugin.DatabaseType.MSSQL)
+          .databaseUrl("jdbc:sqlserver://localhost:1433;database=" + properties.projectBaseName().name() + ";trustServerCertificate=true")
+          .user("SA")
+          .inputSchema("model")
+          .password(MSSQL_PASSWORD)
+          .getConfiguration())
+        .build())
+      .and()
+      .springMainProperties()
+      .set(
+        propertyKey(SPRING_DATASOURCE_URL),
+        propertyValue("jdbc:sqlserver://localhost:1433;database=" + properties.projectBaseName().name() + ";trustServerCertificate=true")
+      )
+      .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("SA"))
+      .set(propertyKey("spring.datasource.password"), propertyValue(MSSQL_PASSWORD))
+      .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("com.microsoft.sqlserver.jdbc.SQLServerDriver"))
+      .and()
+      .springTestProperties()
+      .set(
+        propertyKey(SPRING_DATASOURCE_URL),
+        propertyValue(
+          "jdbc:tc:sqlserver:///;database=" + properties.projectBaseName().name() + ";trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw"
+        )
+      )
+      .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("SA"))
+      .set(propertyKey("spring.datasource.password"), propertyValue(MSSQL_PASSWORD))
+      .and()
+      .mandatoryReplacements()
+      .in(path("src/test/java").append(properties.basePackage().path()).append("IntegrationTest.java"))
+      .add(
+        lineBeforeText("import org.springframework.boot.test.context.SpringBootTest;"),
+        "import org.junit.jupiter.api.extension.ExtendWith;"
+      )
+      .add(lineBeforeText("public @interface"), "@ExtendWith(MsSQLTestContainerExtension.class)")
+      .and()
+      .and()
+      .springMainLogger("com.microsoft.sqlserver", LogLevel.WARN)
+      .springMainLogger("org.reflections", LogLevel.WARN)
       .build();
     //@formatter:on
   }
-
-  private static String mssqlPluginConfiguration(JHipsterModuleProperties properties) {
-    return JooqModuleCodegenConfiguration.builder()
-      .databaseUrl("jdbc:sqlserver://localhost:1433;database=" + properties.projectBaseName().name() + ";trustServerCertificate=true")
-      .user("SA")
-      .inputSchema("model")
-      .jooqMetaDatabase("org.jooq.meta.sqlserver.SQLServerDatabase")
-      .password("yourStrong(!)Password")
-      .build()
-      .getConfiguration();
-  }
-
-  public static JHipsterModule.JHipsterModuleBuilder commonModuleBuilder(JHipsterModuleProperties properties) {
-    Assert.notNull("properties", properties);
-
-    return moduleBuilder(properties)
-      .javaDependencies()
-      .addDependency(groupId("org.springframework.boot"), artifactId("spring-boot-starter-jooq"))
-      .and();
-  }
-
-  private static MavenPlugin jooqMavenCodegenPlugin(String pluginConfiguration) {
-    return mavenPlugin()
-      .groupId("org.jooq")
-      .artifactId("jooq-codegen-maven")
-      .versionSlug("jooq")
-      .addExecution(pluginExecution().goals("generate").id("jooq-codegen").phase(GENERATE_RESOURCES))
-      .configuration(pluginConfiguration)
-      .build();
-  }
 }
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/infrastructure/primary/JooqModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/infrastructure/primary/JooqModuleConfiguration.java
index a3eca2e1f..b21ddcec1 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/infrastructure/primary/JooqModuleConfiguration.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/infrastructure/primary/JooqModuleConfiguration.java
@@ -1,14 +1,11 @@
 package tech.jhipster.lite.generator.server.springboot.database.jooq.infrastructure.primary;
 
 import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.JOOQ;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MARIADB;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MSSQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MYSQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_POSTGRESQL;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JOOQ_MARIADB;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JOOQ_MSSQL;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JOOQ_MYSQL;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JOOQ_POSTGRESQL;
+import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.SPRING_BOOT;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -28,7 +25,7 @@ class JooqModuleConfiguration {
       .slug(JOOQ_POSTGRESQL)
       .propertiesDefinition(properties())
       .apiDoc(API_DOC_GROUP, "Add Jooq with Postgresql to project")
-      .organization(JHipsterModuleOrganization.builder().feature(JOOQ).addDependency(DATASOURCE_POSTGRESQL).build())
+      .organization(organization())
       .tags(tags())
       .factory(postgresql::buildPostgresql);
   }
@@ -39,7 +36,7 @@ class JooqModuleConfiguration {
       .slug(JOOQ_MARIADB)
       .propertiesDefinition(properties())
       .apiDoc(API_DOC_GROUP, "Add Jooq with MariaDB to project")
-      .organization(JHipsterModuleOrganization.builder().feature(JOOQ).addDependency(DATASOURCE_MARIADB).build())
+      .organization(organization())
       .tags(tags())
       .factory(applicationService::buildMariaDB);
   }
@@ -50,7 +47,7 @@ class JooqModuleConfiguration {
       .slug(JOOQ_MYSQL)
       .propertiesDefinition(properties())
       .apiDoc(API_DOC_GROUP, "Add Jooq with MySQL to project")
-      .organization(JHipsterModuleOrganization.builder().feature(JOOQ).addDependency(DATASOURCE_MYSQL).build())
+      .organization(organization())
       .tags(tags())
       .factory(applicationService::buildMySQL);
   }
@@ -61,7 +58,7 @@ class JooqModuleConfiguration {
       .slug(JOOQ_MSSQL)
       .propertiesDefinition(properties())
       .apiDoc(API_DOC_GROUP, "Add Jooq with MsSQL to project")
-      .organization(JHipsterModuleOrganization.builder().feature(JOOQ).addDependency(DATASOURCE_MSSQL).build())
+      .organization(organization())
       .tags(tags())
       .factory(applicationService::buildMsSQL);
   }
@@ -75,6 +72,10 @@ class JooqModuleConfiguration {
       .build();
   }
 
+  private static JHipsterModuleOrganization organization() {
+    return JHipsterModuleOrganization.builder().feature(JOOQ).addDependency(SPRING_BOOT).build();
+  }
+
   private static String[] tags() {
     return new String[] { "server", "spring", "spring-boot", "database" };
   }
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/application/JpaApplicationService.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/application/JpaApplicationService.java
index 3bf50ea9f..8a9c8601a 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/application/JpaApplicationService.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/application/JpaApplicationService.java
@@ -3,6 +3,7 @@ package tech.jhipster.lite.generator.server.springboot.database.jpa.application;
 import org.springframework.stereotype.Service;
 import tech.jhipster.lite.generator.server.springboot.database.jpa.domain.JpaModuleFactory;
 import tech.jhipster.lite.module.domain.JHipsterModule;
+import tech.jhipster.lite.module.domain.docker.DockerImages;
 import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
 
 @Service
@@ -10,8 +11,8 @@ public class JpaApplicationService {
 
   private final JpaModuleFactory factory;
 
-  public JpaApplicationService() {
-    factory = new JpaModuleFactory();
+  public JpaApplicationService(DockerImages dockerImages) {
+    factory = new JpaModuleFactory(dockerImages);
   }
 
   public JHipsterModule buildPostgresql(JHipsterModuleProperties properties) {
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/DatabaseType.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/DatabaseType.java
new file mode 100644
index 000000000..37ce0b567
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/DatabaseType.java
@@ -0,0 +1,18 @@
+package tech.jhipster.lite.generator.server.springboot.database.jpa.domain;
+
+enum DatabaseType {
+  POSTGRESQL("postgresql"),
+  MYSQL("mysql"),
+  MARIADB("mariadb"),
+  MSSQL("mssql");
+
+  private final String id;
+
+  DatabaseType(String id) {
+    this.id = id;
+  }
+
+  public String id() {
+    return id;
+  }
+}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/JpaModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/JpaModuleFactory.java
index a5307661d..ced259dbc 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/JpaModuleFactory.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/JpaModuleFactory.java
@@ -1,96 +1,174 @@
 package tech.jhipster.lite.generator.server.springboot.database.jpa.domain;
 
+import static tech.jhipster.lite.generator.server.springboot.database.jpa.domain.SQLCommonModuleBuilder.sqlCommonModuleBuilder;
 import static tech.jhipster.lite.module.domain.JHipsterModule.artifactId;
+import static tech.jhipster.lite.module.domain.JHipsterModule.documentationTitle;
 import static tech.jhipster.lite.module.domain.JHipsterModule.from;
 import static tech.jhipster.lite.module.domain.JHipsterModule.groupId;
-import static tech.jhipster.lite.module.domain.JHipsterModule.moduleBuilder;
+import static tech.jhipster.lite.module.domain.JHipsterModule.javaDependency;
+import static tech.jhipster.lite.module.domain.JHipsterModule.lineBeforeText;
+import static tech.jhipster.lite.module.domain.JHipsterModule.path;
 import static tech.jhipster.lite.module.domain.JHipsterModule.propertyKey;
 import static tech.jhipster.lite.module.domain.JHipsterModule.propertyValue;
-import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcMainJava;
+import static tech.jhipster.lite.module.domain.JHipsterModule.to;
+import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcTestJava;
 
 import tech.jhipster.lite.module.domain.JHipsterModule;
 import tech.jhipster.lite.module.domain.LogLevel;
-import tech.jhipster.lite.module.domain.file.JHipsterDestination;
+import tech.jhipster.lite.module.domain.docker.DockerImageVersion;
+import tech.jhipster.lite.module.domain.docker.DockerImages;
 import tech.jhipster.lite.module.domain.file.JHipsterSource;
-import tech.jhipster.lite.module.domain.javaproperties.PropertyValue;
+import tech.jhipster.lite.module.domain.javadependency.JavaDependency;
+import tech.jhipster.lite.module.domain.javadependency.JavaDependencyScope;
 import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
-import tech.jhipster.lite.shared.error.domain.Assert;
 
 public class JpaModuleFactory {
 
-  private static final String ORG_HIBERNATE = "org.hibernate.orm";
-  private static final PropertyValue FALSE = propertyValue(false);
-  private static final PropertyValue TRUE = propertyValue(true);
+  public static final String ORG_POSTGRESQL = "org.postgresql";
+  private static final String MYSQL = "mysql";
+  private static final String MYSQL_GROUP_ID = "com.mysql";
+  private static final String MYSQL_ARTIFACT_ID = "mysql-connector-j";
+
+  private static final String SPRING_DATASOURCE_URL = "spring.datasource.url";
+  private static final String SPRING_DATASOURCE_USERNAME = "spring.datasource.username";
+  private static final String SPRING_DATASOURCE_DRIVER_CLASS_NAME = "spring.datasource.driver-class-name";
+
+  private final DockerImages dockerImages;
+
+  public JpaModuleFactory(DockerImages dockerImages) {
+    this.dockerImages = dockerImages;
+  }
 
   public JHipsterModule buildPostgresql(JHipsterModuleProperties properties) {
-    return sqlCommonModuleBuilder(properties).build();
+    DockerImageVersion dockerImage = dockerImages.get("postgres");
+
+    //@formatter:off
+    return sqlCommonModuleBuilder(
+      properties,
+      DatabaseType.POSTGRESQL,
+      dockerImage,
+      documentationTitle("Postgresql"),
+      artifactId("postgresql")
+    )
+      .javaDependencies()
+        .addDependency(
+          JavaDependency.builder()
+            .groupId(groupId(ORG_POSTGRESQL))
+            .artifactId(artifactId("postgresql"))
+            .scope(JavaDependencyScope.RUNTIME)
+            .build()
+        )
+        .and()
+      .springMainProperties()
+        .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:postgresql://localhost:5432/" + properties.projectBaseName().name()))
+        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue(properties.projectBaseName().name()))
+        .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("org.postgresql.Driver"))
+        .and()
+      .springTestProperties()
+        .set(
+          propertyKey(SPRING_DATASOURCE_URL),
+          propertyValue(
+            "jdbc:tc:postgresql:" + dockerImage.version().get() + ":///" + properties.projectBaseName().name() + "?TC_TMPFS=/testtmpfs:rw"
+          )
+        )
+        .and()
+      .springMainLogger(ORG_POSTGRESQL, LogLevel.WARN)
+      .springTestLogger(ORG_POSTGRESQL, LogLevel.WARN)
+      .springTestLogger("org.jboss.logging", LogLevel.WARN)
+      .build();
+    //@formatter:on
   }
 
   public JHipsterModule buildMariaDB(JHipsterModuleProperties properties) {
-    return sqlCommonModuleBuilder(properties).build();
+    //@formatter:off
+    return sqlCommonModuleBuilder(
+      properties,
+      DatabaseType.MARIADB,
+      dockerImages.get("mariadb"),
+      documentationTitle("MariaDB"),
+      artifactId("mariadb")
+    )
+      .javaDependencies()
+        .addDependency(
+          javaDependency().groupId("org.mariadb.jdbc").artifactId("mariadb-java-client").scope(JavaDependencyScope.RUNTIME).build()
+        )
+        .and()
+      .springMainProperties()
+        .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:mariadb://localhost:3306/" + properties.projectBaseName().name()))
+        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("root"))
+        .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("org.mariadb.jdbc.Driver"))
+        .and()
+      .build();
+    //@formatter:on
   }
 
   public JHipsterModule buildMySQL(JHipsterModuleProperties properties) {
-    return sqlCommonModuleBuilder(properties).build();
-  }
-
-  public JHipsterModule buildMsSQL(JHipsterModuleProperties properties) {
     //@formatter:off
-    return sqlCommonModuleBuilder(properties)
+    return sqlCommonModuleBuilder(properties, DatabaseType.MYSQL, dockerImages.get(MYSQL), documentationTitle("MySQL"), artifactId(MYSQL))
+      .javaDependencies()
+        .addDependency(javaDependency().groupId(MYSQL_GROUP_ID).artifactId(MYSQL_ARTIFACT_ID).scope(JavaDependencyScope.RUNTIME).build())
+        .and()
       .springMainProperties()
-        .set(propertyKey("spring.jpa.hibernate.ddl-auto"), propertyValue("update"))
-        .set(propertyKey("spring.jpa.properties.hibernate.criteria.literal_handling_mode"), propertyValue("BIND"))
-        .set(propertyKey("spring.jpa.properties.hibernate.dialect"), propertyValue("org.hibernate.dialect.SQLServer2012Dialect"))
-        .set(propertyKey("spring.jpa.properties.hibernate.format_sql"), propertyValue(true))
-        .set(propertyKey("spring.jpa.properties.hibernate.jdbc.fetch_size"), propertyValue(150))
+        .set(propertyKey(SPRING_DATASOURCE_URL), propertyValue("jdbc:mysql://localhost:3306/" + properties.projectBaseName().name()))
+        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("root"))
+        .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("com.mysql.cj.jdbc.Driver"))
         .and()
       .build();
     //@formatter:on
   }
 
-  public static JHipsterModule.JHipsterModuleBuilder sqlCommonModuleBuilder(JHipsterModuleProperties properties) {
-    Assert.notNull("properties", properties);
-
-    JHipsterSource jpaSource = from("server/springboot/database/jpa");
-    JHipsterDestination mainDestination = toSrcMainJava()
-      .append(properties.packagePath())
-      .append("wire/database/infrastructure/secondary/");
+  public JHipsterModule buildMsSQL(JHipsterModuleProperties properties) {
+    DockerImageVersion dockerImage = dockerImages.get("mcr.microsoft.com/mssql/server");
+    JHipsterSource source = from("server/springboot/database/common");
 
     //@formatter:off
-    return moduleBuilder(properties)
+    return sqlCommonModuleBuilder(properties, DatabaseType.MSSQL, dockerImage, documentationTitle("MsSQL"), artifactId("mssqlserver"))
       .files()
-        .add(jpaSource.template("DatabaseConfiguration.java"), mainDestination.append("DatabaseConfiguration.java"))
+        .add(source.append("docker").template("container-license-acceptance.txt"), to("src/test/resources/container-license-acceptance.txt"))
+        .add(
+          source.template("MsSQLTestContainerExtension.java"),
+          toSrcTestJava().append(properties.basePackage().path()).append("MsSQLTestContainerExtension.java")
+        )
         .and()
       .javaDependencies()
-        .addDependency(groupId("org.springframework.boot"), artifactId("spring-boot-starter-data-jpa"))
-        .addDependency(groupId(ORG_HIBERNATE), artifactId("hibernate-core"))
+        .addDependency(javaDependency().groupId("com.microsoft.sqlserver").artifactId("mssql-jdbc").scope(JavaDependencyScope.RUNTIME).build())
         .and()
       .springMainProperties()
-        .set(propertyKey("spring.data.jpa.repositories.bootstrap-mode"), propertyValue("deferred"))
-        .set(propertyKey("spring.jpa.hibernate.ddl-auto"), propertyValue("none"))
         .set(
-          propertyKey("spring.jpa.hibernate.naming.implicit-strategy"),
-          propertyValue("org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy")
+          propertyKey(SPRING_DATASOURCE_URL),
+          propertyValue("jdbc:sqlserver://localhost:1433;database=" + properties.projectBaseName().name() + ";trustServerCertificate=true")
         )
+        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("SA"))
+        .set(propertyKey("spring.datasource.password"), propertyValue("yourStrong(!)Password"))
+        .set(propertyKey(SPRING_DATASOURCE_DRIVER_CLASS_NAME), propertyValue("com.microsoft.sqlserver.jdbc.SQLServerDriver"))
+        .set(propertyKey("spring.jpa.hibernate.ddl-auto"), propertyValue("update"))
+        .set(propertyKey("spring.jpa.properties.hibernate.criteria.literal_handling_mode"), propertyValue("BIND"))
+        .set(propertyKey("spring.jpa.properties.hibernate.dialect"), propertyValue("org.hibernate.dialect.SQLServer2012Dialect"))
+        .set(propertyKey("spring.jpa.properties.hibernate.format_sql"), propertyValue(true))
+        .set(propertyKey("spring.jpa.properties.hibernate.jdbc.fetch_size"), propertyValue(150))
+        .and()
+      .springTestProperties()
         .set(
-          propertyKey("spring.jpa.hibernate.naming.physical-strategy"),
-          propertyValue("org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy")
+          propertyKey(SPRING_DATASOURCE_URL),
+          propertyValue(
+            "jdbc:tc:sqlserver:///;database=" + properties.projectBaseName().name() + ";trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw"
+          )
         )
-        .set(propertyKey("spring.jpa.open-in-view"), FALSE)
-        .set(propertyKey("spring.jpa.properties.hibernate.connection.provider_disables_autocommit"), TRUE)
-        .set(propertyKey("spring.jpa.properties.hibernate.generate_statistics"), FALSE)
-        .set(propertyKey("spring.jpa.properties.hibernate.jdbc.batch_size"), propertyValue(25))
-        .set(propertyKey("spring.jpa.properties.hibernate.jdbc.time_zone"), propertyValue("UTC"))
-        .set(propertyKey("spring.jpa.properties.hibernate.order_inserts"), TRUE)
-        .set(propertyKey("spring.jpa.properties.hibernate.order_updates"), TRUE)
-        .set(propertyKey("spring.jpa.properties.hibernate.query.fail_on_pagination_over_collection_fetch"), TRUE)
-        .set(propertyKey("spring.jpa.properties.hibernate.query.in_clause_parameter_padding"), TRUE)
+        .set(propertyKey(SPRING_DATASOURCE_USERNAME), propertyValue("SA"))
+        .set(propertyKey("spring.datasource.password"), propertyValue("yourStrong(!)Password"))
         .and()
-      .springMainLogger(ORG_HIBERNATE, LogLevel.WARN)
-      .springMainLogger("org.hibernate.ejb.HibernatePersistence", LogLevel.OFF)
-      .springTestLogger("org.hibernate.validator", LogLevel.WARN)
-      .springTestLogger(ORG_HIBERNATE, LogLevel.WARN)
-      .springTestLogger("org.hibernate.ejb.HibernatePersistence", LogLevel.OFF);
+      .mandatoryReplacements()
+        .in(path("src/test/java").append(properties.basePackage().path()).append("IntegrationTest.java"))
+          .add(
+            lineBeforeText("import org.springframework.boot.test.context.SpringBootTest;"),
+            "import org.junit.jupiter.api.extension.ExtendWith;"
+          )
+          .add(lineBeforeText("public @interface"), "@ExtendWith(MsSQLTestContainerExtension.class)")
+          .and()
+        .and()
+      .springMainLogger("com.microsoft.sqlserver", LogLevel.WARN)
+      .springMainLogger("org.reflections", LogLevel.WARN)
+      .build();
     //@formatter:on
   }
 }
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/SQLCommonModuleBuilder.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/SQLCommonModuleBuilder.java
new file mode 100644
index 000000000..057f43a31
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/SQLCommonModuleBuilder.java
@@ -0,0 +1,136 @@
+package tech.jhipster.lite.generator.server.springboot.database.jpa.domain;
+
+import static tech.jhipster.lite.module.domain.JHipsterModule.JHipsterModuleBuilder;
+import static tech.jhipster.lite.module.domain.JHipsterModule.artifactId;
+import static tech.jhipster.lite.module.domain.JHipsterModule.from;
+import static tech.jhipster.lite.module.domain.JHipsterModule.groupId;
+import static tech.jhipster.lite.module.domain.JHipsterModule.javaDependency;
+import static tech.jhipster.lite.module.domain.JHipsterModule.moduleBuilder;
+import static tech.jhipster.lite.module.domain.JHipsterModule.propertyKey;
+import static tech.jhipster.lite.module.domain.JHipsterModule.propertyValue;
+import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcMainDocker;
+import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcMainJava;
+
+import tech.jhipster.lite.module.domain.DocumentationTitle;
+import tech.jhipster.lite.module.domain.LogLevel;
+import tech.jhipster.lite.module.domain.docker.DockerImageVersion;
+import tech.jhipster.lite.module.domain.file.JHipsterDestination;
+import tech.jhipster.lite.module.domain.file.JHipsterSource;
+import tech.jhipster.lite.module.domain.javabuild.ArtifactId;
+import tech.jhipster.lite.module.domain.javadependency.JavaDependency;
+import tech.jhipster.lite.module.domain.javadependency.JavaDependencyScope;
+import tech.jhipster.lite.module.domain.javaproperties.PropertyValue;
+import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
+import tech.jhipster.lite.shared.error.domain.Assert;
+
+final class SQLCommonModuleBuilder {
+
+  private static final String ORG_HIBERNATE = "org.hibernate.orm";
+  private static final PropertyValue FALSE = propertyValue(false);
+  private static final PropertyValue TRUE = propertyValue(true);
+
+  private SQLCommonModuleBuilder() {}
+
+  public static JHipsterModuleBuilder sqlCommonModuleBuilder(
+    JHipsterModuleProperties properties,
+    DatabaseType databaseType,
+    DockerImageVersion dockerImage,
+    DocumentationTitle documentationTitle,
+    ArtifactId testContainerArtifactId
+  ) {
+    Assert.notNull("properties", properties);
+    Assert.notNull("databaseType", databaseType);
+    Assert.notNull("dockerImage", dockerImage);
+    Assert.notNull("documentationTitle", documentationTitle);
+    Assert.notNull("testContainerArtifactId", testContainerArtifactId);
+
+    String databaseId = databaseType.id();
+    JHipsterSource commonSource = from("server/springboot/database/common");
+    JHipsterSource jpaSource = from("server/springboot/database/jpa");
+    JHipsterDestination mainDestination = toSrcMainJava()
+      .append(properties.packagePath())
+      .append("wire")
+      .append(databaseId)
+      .append("infrastructure/secondary/");
+
+    //@formatter:off
+    return moduleBuilder(properties)
+      .context()
+        .put("srcMainDocker", "src/main/docker") // To be used in <databaseId>>.md file
+        .put("databaseType", databaseId)
+        .put(databaseId + "DockerImageWithVersion", dockerImage.fullName()) // To be used in <databaseId>.yml docker-compose file
+        .and()
+      .documentation(documentationTitle, commonSource.template("databaseType.md"))
+      .startupCommands()
+        .dockerCompose(startupCommand(databaseId))
+        .and()
+      .files()
+        .add(jpaSource.template("DatabaseConfiguration.java"), mainDestination.append("DatabaseConfiguration.java"))
+        .add(commonSource.append("docker").template(databaseId + ".yml"), toSrcMainDocker().append(databaseId + ".yml"))
+        .and()
+      .javaDependencies()
+        .addDependency(groupId("org.springframework.boot"), artifactId("spring-boot-starter-data-jpa"))
+        .addDependency(groupId("com.zaxxer"), artifactId("HikariCP"))
+        .addDependency(groupId(ORG_HIBERNATE), artifactId("hibernate-core"))
+        .addDependency(testContainer(testContainerArtifactId))
+        .and()
+      .springMainProperties()
+        .set(propertyKey("spring.datasource.password"), propertyValue(""))
+        .set(propertyKey("spring.datasource.type"), propertyValue("com.zaxxer.hikari.HikariDataSource"))
+        .set(propertyKey("spring.datasource.hikari.poolName"), propertyValue("Hikari"))
+        .set(propertyKey("spring.datasource.hikari.auto-commit"), FALSE)
+        .set(propertyKey("spring.data.jpa.repositories.bootstrap-mode"), propertyValue("deferred"))
+        .set(propertyKey("spring.jpa.hibernate.ddl-auto"), propertyValue("none"))
+        .set(
+          propertyKey("spring.jpa.hibernate.naming.implicit-strategy"),
+          propertyValue("org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy")
+        )
+        .set(
+          propertyKey("spring.jpa.hibernate.naming.physical-strategy"),
+          propertyValue("org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy")
+        )
+        .set(propertyKey("spring.jpa.open-in-view"), FALSE)
+        .set(propertyKey("spring.jpa.properties.hibernate.connection.provider_disables_autocommit"), TRUE)
+        .set(propertyKey("spring.jpa.properties.hibernate.generate_statistics"), FALSE)
+        .set(propertyKey("spring.jpa.properties.hibernate.jdbc.batch_size"), propertyValue(25))
+        .set(propertyKey("spring.jpa.properties.hibernate.jdbc.time_zone"), propertyValue("UTC"))
+        .set(propertyKey("spring.jpa.properties.hibernate.order_inserts"), TRUE)
+        .set(propertyKey("spring.jpa.properties.hibernate.order_updates"), TRUE)
+        .set(propertyKey("spring.jpa.properties.hibernate.query.fail_on_pagination_over_collection_fetch"), TRUE)
+        .set(propertyKey("spring.jpa.properties.hibernate.query.in_clause_parameter_padding"), TRUE)
+        .and()
+      .springTestProperties()
+        .set(
+          propertyKey("spring.datasource.url"),
+          propertyValue("jdbc:tc:" + dockerImage.fullName() + ":///" + properties.projectBaseName().name())
+        )
+        .set(propertyKey("spring.datasource.username"), propertyValue(properties.projectBaseName().name()))
+        .set(propertyKey("spring.datasource.password"), propertyValue(""))
+        .set(propertyKey("spring.datasource.driver-class-name"), propertyValue("org.testcontainers.jdbc.ContainerDatabaseDriver"))
+        .set(propertyKey("spring.datasource.hikari.maximum-pool-size"), propertyValue(2))
+        .and()
+      .springMainLogger("org.hibernate.validator", LogLevel.WARN)
+      .springMainLogger(ORG_HIBERNATE, LogLevel.WARN)
+      .springMainLogger("org.hibernate.ejb.HibernatePersistence", LogLevel.OFF)
+      .springTestLogger("org.hibernate.validator", LogLevel.WARN)
+      .springTestLogger(ORG_HIBERNATE, LogLevel.WARN)
+      .springTestLogger("org.hibernate.ejb.HibernatePersistence", LogLevel.OFF)
+      .springTestLogger("com.github.dockerjava", LogLevel.WARN)
+      .springTestLogger("org.testcontainers", LogLevel.WARN);
+    //@formatter:on
+  }
+
+  private static JavaDependency testContainer(ArtifactId testContainerArtifactId) {
+    return javaDependency()
+      .groupId("org.testcontainers")
+      .artifactId(testContainerArtifactId)
+      .dependencySlug("%s-%s".formatted("testcontainers", testContainerArtifactId))
+      .versionSlug("testcontainers")
+      .scope(JavaDependencyScope.TEST)
+      .build();
+  }
+
+  private static String startupCommand(String databaseId) {
+    return "src/main/docker/" + databaseId + ".yml";
+  }
+}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/infrastructure/primary/JpaModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/infrastructure/primary/JpaModuleConfiguration.java
index 2ad722f1b..ebaf035fd 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/infrastructure/primary/JpaModuleConfiguration.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jpa/infrastructure/primary/JpaModuleConfiguration.java
@@ -1,14 +1,11 @@
 package tech.jhipster.lite.generator.server.springboot.database.jpa.infrastructure.primary;
 
 import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.JPA_PERSISTENCE;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MARIADB;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MSSQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MYSQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_POSTGRESQL;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JPA_MARIADB;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JPA_MSSQL;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JPA_MYSQL;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JPA_POSTGRESQL;
+import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.SPRING_BOOT;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -28,7 +25,7 @@ class JpaModuleConfiguration {
       .slug(JPA_POSTGRESQL)
       .propertiesDefinition(properties())
       .apiDoc(API_DOC_GROUP, "Add JPA with Postgresql to project")
-      .organization(JHipsterModuleOrganization.builder().feature(JPA_PERSISTENCE).addDependency(DATASOURCE_POSTGRESQL).build())
+      .organization(organization())
       .tags(tags())
       .factory(postgresql::buildPostgresql);
   }
@@ -39,7 +36,7 @@ class JpaModuleConfiguration {
       .slug(JPA_MARIADB)
       .propertiesDefinition(properties())
       .apiDoc(API_DOC_GROUP, "Add JPA with MariaDB to project")
-      .organization(JHipsterModuleOrganization.builder().feature(JPA_PERSISTENCE).addDependency(DATASOURCE_MARIADB).build())
+      .organization(organization())
       .tags(tags())
       .factory(applicationService::buildMariaDB);
   }
@@ -50,7 +47,7 @@ class JpaModuleConfiguration {
       .slug(JPA_MYSQL)
       .propertiesDefinition(properties())
       .apiDoc(API_DOC_GROUP, "Add JPA with MySQL to project")
-      .organization(JHipsterModuleOrganization.builder().feature(JPA_PERSISTENCE).addDependency(DATASOURCE_MYSQL).build())
+      .organization(organization())
       .tags(tags())
       .factory(applicationService::buildMySQL);
   }
@@ -61,7 +58,7 @@ class JpaModuleConfiguration {
       .slug(JPA_MSSQL)
       .propertiesDefinition(properties())
       .apiDoc(API_DOC_GROUP, "Add JPA with MsSQL to project")
-      .organization(JHipsterModuleOrganization.builder().feature(JPA_PERSISTENCE).addDependency(DATASOURCE_MSSQL).build())
+      .organization(organization())
       .tags(tags())
       .factory(applicationService::buildMsSQL);
   }
@@ -75,6 +72,10 @@ class JpaModuleConfiguration {
       .build();
   }
 
+  private static JHipsterModuleOrganization organization() {
+    return JHipsterModuleOrganization.builder().feature(JPA_PERSISTENCE).addDependency(SPRING_BOOT).build();
+  }
+
   private static String[] tags() {
     return new String[] { "server", "spring", "spring-boot", "database" };
   }
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/flyway/infrastructure/primary/FlywayModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/flyway/infrastructure/primary/FlywayModuleConfiguration.java
index f43a4b003..1ee8ca90d 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/flyway/infrastructure/primary/FlywayModuleConfiguration.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/flyway/infrastructure/primary/FlywayModuleConfiguration.java
@@ -1,16 +1,16 @@
 package tech.jhipster.lite.generator.server.springboot.dbmigration.flyway.infrastructure.primary;
 
 import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.DATABASE_MIGRATION;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.DATASOURCE;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MARIADB;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MSSQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_MYSQL;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.DATASOURCE_POSTGRESQL;
+import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.JPA_PERSISTENCE;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.FLYWAY;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.FLYWAY_MARIADB;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.FLYWAY_MSSQL;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.FLYWAY_MYSQL;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.FLYWAY_POSTGRESQL;
+import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JPA_MARIADB;
+import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JPA_MSSQL;
+import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JPA_MYSQL;
+import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.JPA_POSTGRESQL;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -32,7 +32,7 @@ class FlywayModuleConfiguration {
         JHipsterModulePropertiesDefinition.builder().addBasePackage().addIndentation().addSpringConfigurationFormat().build()
       )
       .apiDoc(API_DOC_GROUP, "Add Flyway")
-      .organization(JHipsterModuleOrganization.builder().feature(DATABASE_MIGRATION).addDependency(DATASOURCE).build())
+      .organization(JHipsterModuleOrganization.builder().feature(DATABASE_MIGRATION).addDependency(JPA_PERSISTENCE).build())
       .tags(flywayTags())
       .factory(flyway::buildInitializationModule);
   }
@@ -43,7 +43,7 @@ class FlywayModuleConfiguration {
       .slug(FLYWAY_MYSQL)
       .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addBasePackage().addIndentation().build())
       .apiDoc(API_DOC_GROUP, "Add Flyway MySQL")
-      .organization(JHipsterModuleOrganization.builder().addDependency(FLYWAY).addDependency(DATASOURCE_MYSQL).build())
+      .organization(JHipsterModuleOrganization.builder().addDependency(FLYWAY).addDependency(JPA_MYSQL).build())
       .tags(flywayTags())
       .factory(flyway::buildMysqlDependencyModule);
   }
@@ -54,7 +54,7 @@ class FlywayModuleConfiguration {
       .slug(FLYWAY_MARIADB)
       .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addBasePackage().addIndentation().build())
       .apiDoc(API_DOC_GROUP, "Add Flyway MariaDB")
-      .organization(JHipsterModuleOrganization.builder().addDependency(FLYWAY).addDependency(DATASOURCE_MARIADB).build())
+      .organization(JHipsterModuleOrganization.builder().addDependency(FLYWAY).addDependency(JPA_MARIADB).build())
       .tags(flywayTags())
       .factory(flyway::buildMysqlDependencyModule);
   }
@@ -65,7 +65,7 @@ class FlywayModuleConfiguration {
       .slug(FLYWAY_POSTGRESQL)
       .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addBasePackage().addIndentation().build())
       .apiDoc(API_DOC_GROUP, "Add Flyway PostgreSQL")
-      .organization(JHipsterModuleOrganization.builder().addDependency(FLYWAY).addDependency(DATASOURCE_POSTGRESQL).build())
+      .organization(JHipsterModuleOrganization.builder().addDependency(FLYWAY).addDependency(JPA_POSTGRESQL).build())
       .tags(flywayTags())
       .factory(flyway::buildPostgresqlDependencyModule);
   }
@@ -76,7 +76,7 @@ class FlywayModuleConfiguration {
       .slug(FLYWAY_MSSQL)
       .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addBasePackage().addIndentation().build())
       .apiDoc(API_DOC_GROUP, "Add Flyway PostgreSQL")
-      .organization(JHipsterModuleOrganization.builder().addDependency(FLYWAY).addDependency(DATASOURCE_MSSQL).build())
+      .organization(JHipsterModuleOrganization.builder().addDependency(FLYWAY).addDependency(JPA_MSSQL).build())
       .tags(flywayTags())
       .factory(flyway::buildMsSqlServerDependencyModule);
   }
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/infrastructure/primary/LiquibaseModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/infrastructure/primary/LiquibaseModuleConfiguration.java
index 156f50c8a..526781884 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/infrastructure/primary/LiquibaseModuleConfiguration.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/infrastructure/primary/LiquibaseModuleConfiguration.java
@@ -1,7 +1,7 @@
 package tech.jhipster.lite.generator.server.springboot.dbmigration.liquibase.infrastructure.primary;
 
 import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.DATABASE_MIGRATION;
-import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.DATASOURCE;
+import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.JPA_PERSISTENCE;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.LIQUIBASE;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.LIQUIBASE_ASYNC;
 import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.LIQUIBASE_LINTER;
@@ -26,7 +26,7 @@ class LiquibaseModuleConfiguration {
       .slug(LIQUIBASE)
       .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addIndentation().addSpringConfigurationFormat().build())
       .apiDoc(SPRING_BOOT_DATABASE_MIGRATION, "Add Liquibase")
-      .organization(JHipsterModuleOrganization.builder().feature(DATABASE_MIGRATION).addDependency(DATASOURCE).build())
+      .organization(JHipsterModuleOrganization.builder().feature(DATABASE_MIGRATION).addDependency(JPA_PERSISTENCE).build())
       .tags(liquibaseTags())
       .factory(liquibase::buildModule);
   }
diff --git a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java
index 906f13104..a7ffc83c7 100644
--- a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java
+++ b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java
@@ -69,6 +69,7 @@ import tech.jhipster.lite.module.domain.javaproperties.SpringProfile;
 import tech.jhipster.lite.module.domain.javaproperties.SpringProperties;
 import tech.jhipster.lite.module.domain.javaproperties.SpringProperty;
 import tech.jhipster.lite.module.domain.javaproperties.SpringPropertyType;
+import tech.jhipster.lite.module.domain.jooqplugin.JooqModuleCodegenConfiguration;
 import tech.jhipster.lite.module.domain.mavenplugin.JHipsterModuleMavenPlugins;
 import tech.jhipster.lite.module.domain.mavenplugin.JHipsterModuleMavenPlugins.JHipsterModuleMavenPluginsBuilder;
 import tech.jhipster.lite.module.domain.mavenplugin.MavenPlugin;
@@ -237,6 +238,10 @@ public final class JHipsterModule {
     return JavaDependency.builder();
   }
 
+  public static JooqModuleCodegenConfiguration.JooqModuleCodegenConfigurationBuilder jooqModuleCodegenConfiguration() {
+    return JooqModuleCodegenConfiguration.builder();
+  }
+
   public static MavenBuildExtensionGroupIdBuilder mavenBuildExtension() {
     return MavenBuildExtension.builder();
   }
diff --git a/src/main/java/tech/jhipster/lite/module/domain/jooqplugin/DatabaseType.java b/src/main/java/tech/jhipster/lite/module/domain/jooqplugin/DatabaseType.java
new file mode 100644
index 000000000..1484212f2
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/module/domain/jooqplugin/DatabaseType.java
@@ -0,0 +1,10 @@
+package tech.jhipster.lite.module.domain.jooqplugin;
+
+//shared enum ??
+
+public enum DatabaseType {
+  POSTGRESQL,
+  MYSQL,
+  MARIADB,
+  MSSQL,
+}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleCodegenConfiguration.java b/src/main/java/tech/jhipster/lite/module/domain/jooqplugin/JooqModuleCodegenConfiguration.java
similarity index 53%
rename from src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleCodegenConfiguration.java
rename to src/main/java/tech/jhipster/lite/module/domain/jooqplugin/JooqModuleCodegenConfiguration.java
index b0da84296..bc18291c9 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleCodegenConfiguration.java
+++ b/src/main/java/tech/jhipster/lite/module/domain/jooqplugin/JooqModuleCodegenConfiguration.java
@@ -1,31 +1,26 @@
-package tech.jhipster.lite.generator.server.springboot.database.jooq.domain;
+package tech.jhipster.lite.module.domain.jooqplugin;
 
-import java.util.Optional;
 import tech.jhipster.lite.shared.error.domain.Assert;
 
-final class JooqModuleCodegenConfiguration {
+public final class JooqModuleCodegenConfiguration {
 
+  private final DatabaseType database;
   private final String databaseUrl;
   private final String user;
   private final String inputSchema;
-  private final String jooqMetaDatabase;
   private final String password;
 
   private JooqModuleCodegenConfiguration(JooqModuleCodegenConfigurationBuilder builder) {
+    Assert.notNull("database", builder.database);
     Assert.notNull("databaseUrl", builder.databaseUrl);
     Assert.notNull("user", builder.user);
     Assert.notNull("inputSchema", builder.inputSchema);
-    Assert.notNull("jooqMetaDatabase", builder.jooqMetaDatabase);
 
+    this.database = builder.database;
     this.databaseUrl = builder.databaseUrl;
     this.user = builder.user;
     this.inputSchema = builder.inputSchema;
-    this.jooqMetaDatabase = builder.jooqMetaDatabase;
-    this.password = Optional.ofNullable(builder.password).orElse("");
-  }
-
-  public static JooqModuleCodegenConfigurationDatabaseUrlBuilder builder() {
-    return new JooqModuleCodegenConfigurationBuilder();
+    this.password = builder.password == null ? "" : builder.password;
   }
 
   public String getConfiguration() {
@@ -51,83 +46,93 @@ final class JooqModuleCodegenConfiguration {
       databaseUrl,
       user,
       password,
-      jooqMetaDatabase,
+      databaseJooqName(),
       inputSchema
     );
   }
 
-  public sealed interface JooqModuleCodegenConfigurationDatabaseUrlBuilder permits JooqModuleCodegenConfigurationBuilder {
-    JooqModuleCodegenConfigurationUserBuilder databaseUrl(String databaseUrl);
+  private String databaseJooqName() {
+    return switch (database) {
+      case POSTGRESQL -> "org.jooq.meta.postgres.PostgresDatabase";
+      case MYSQL -> "org.jooq.meta.mysql.MySQLDatabase";
+      case MARIADB -> "org.jooq.meta.mariadb.MariaDBDatabase";
+      case MSSQL -> "org.jooq.meta.sqlserver.SQLServerDatabase";
+    };
   }
 
-  public sealed interface JooqModuleCodegenConfigurationUserBuilder permits JooqModuleCodegenConfigurationBuilder {
-    JooqModuleCodegenConfigurationInputSchemaBuilder user(String user);
+  public static JooqModuleCodegenConfigurationBuilder builder() {
+    return new JooqModuleCodegenConfigurationBuilder();
   }
 
-  public sealed interface JooqModuleCodegenConfigurationInputSchemaBuilder permits JooqModuleCodegenConfigurationBuilder {
-    JooqModuleCodegenConfigurationJooqMetaDatabaseBuilder inputSchema(String inputSchema);
+  public interface JooqModuleCodegenConfigurationDatabaseBuilder {
+    JooqModuleCodegenConfigurationDatabaseUrlBuilder database(DatabaseType database);
   }
 
-  public sealed interface JooqModuleCodegenConfigurationJooqMetaDatabaseBuilder permits JooqModuleCodegenConfigurationBuilder {
-    JooqModuleCodegenConfigurationOptionalBuilder jooqMetaDatabase(String jooqMetaDatabase);
+  public interface JooqModuleCodegenConfigurationDatabaseUrlBuilder {
+    JooqModuleCodegenConfigurationUserBuilder databaseUrl(String databaseUrl);
+  }
+
+  public interface JooqModuleCodegenConfigurationUserBuilder {
+    JooqModuleCodegenConfigurationInputSchemaBuilder user(String user);
   }
 
-  public sealed interface JooqModuleCodegenConfigurationOptionalBuilder permits JooqModuleCodegenConfigurationBuilder {
-    JooqModuleCodegenConfigurationOptionalBuilder password(String password);
+  public interface JooqModuleCodegenConfigurationInputSchemaBuilder {
+    JooqModuleCodegenConfigurationBuilder inputSchema(String inputSchema);
+  }
 
-    JooqModuleCodegenConfiguration build();
+  public interface JooqModuleCodegenConfigurationPasswordBuilder {
+    JooqModuleCodegenConfiguration password(String password);
   }
 
-  private static final class JooqModuleCodegenConfigurationBuilder
+  public static final class JooqModuleCodegenConfigurationBuilder
     implements
+      JooqModuleCodegenConfigurationDatabaseBuilder,
       JooqModuleCodegenConfigurationDatabaseUrlBuilder,
       JooqModuleCodegenConfigurationUserBuilder,
       JooqModuleCodegenConfigurationInputSchemaBuilder,
-      JooqModuleCodegenConfigurationJooqMetaDatabaseBuilder,
-      JooqModuleCodegenConfigurationOptionalBuilder {
+      JooqModuleCodegenConfigurationPasswordBuilder {
 
+    private DatabaseType database;
     private String databaseUrl;
     private String user;
     private String inputSchema;
-    private String jooqMetaDatabase;
     private String password;
 
     @Override
-    public JooqModuleCodegenConfigurationUserBuilder databaseUrl(String databaseUrl) {
-      this.databaseUrl = databaseUrl;
+    public JooqModuleCodegenConfigurationDatabaseUrlBuilder database(DatabaseType database) {
+      this.database = database;
 
       return this;
     }
 
     @Override
-    public JooqModuleCodegenConfigurationInputSchemaBuilder user(String user) {
-      this.user = user;
+    public JooqModuleCodegenConfigurationUserBuilder databaseUrl(String databaseUrl) {
+      this.databaseUrl = databaseUrl;
 
       return this;
     }
 
     @Override
-    public JooqModuleCodegenConfigurationJooqMetaDatabaseBuilder inputSchema(String inputSchema) {
-      this.inputSchema = inputSchema;
+    public JooqModuleCodegenConfigurationInputSchemaBuilder user(String user) {
+      this.user = user;
 
       return this;
     }
 
     @Override
-    public JooqModuleCodegenConfigurationOptionalBuilder jooqMetaDatabase(String jooqMetaDatabase) {
-      this.jooqMetaDatabase = jooqMetaDatabase;
+    public JooqModuleCodegenConfigurationBuilder inputSchema(String inputSchema) {
+      this.inputSchema = inputSchema;
 
       return this;
     }
 
     @Override
-    public JooqModuleCodegenConfigurationOptionalBuilder password(String password) {
+    public JooqModuleCodegenConfiguration password(String password) {
       this.password = password;
 
-      return this;
+      return build();
     }
 
-    @Override
     public JooqModuleCodegenConfiguration build() {
       return new JooqModuleCodegenConfiguration(this);
     }
diff --git a/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteFeatureSlug.java b/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteFeatureSlug.java
index a3f3a8070..0eb9a7a86 100644
--- a/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteFeatureSlug.java
+++ b/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteFeatureSlug.java
@@ -10,7 +10,6 @@ public enum JHLiteFeatureSlug implements JHipsterFeatureSlugFactory {
   CLIENT_CORE("client-core"),
   CLIENT_INTERNATIONALIZATION("client-internationalization"),
   CUCUMBER_AUTHENTICATION("cucumber-authentication"),
-  DATASOURCE("datasource"),
   DATABASE_MIGRATION("database-migration"),
   DOCKERFILE("dockerfile"),
   E2E_TESTS("e2e-tests"),
diff --git a/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteModuleSlug.java b/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteModuleSlug.java
index 79a49a374..be0da5ffd 100644
--- a/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteModuleSlug.java
+++ b/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteModuleSlug.java
@@ -22,10 +22,6 @@ public enum JHLiteModuleSlug implements JHipsterModuleSlugFactory {
   CUSTOM_JHLITE("custom-jhlite"),
   CYPRESS_COMPONENT_TESTS("cypress-component-tests"),
   CYPRESS_E2E("cypress-e2e"),
-  DATASOURCE_MARIADB("datasource-mariadb"),
-  DATASOURCE_MSSQL("datasource-mssql"),
-  DATASOURCE_MYSQL("datasource-mysql"),
-  DATASOURCE_POSTGRESQL("datasource-postgresql"),
   DOCKERFILE_MAVEN("dockerfile-maven"),
   DOCKERFILE_GRADLE("dockerfile-gradle"),
   EHCACHE_JAVA_CONFIG("ehcache-java-config"),
diff --git a/src/main/resources/generator/client/angular/admin/src/main/webapp/app/admin/health/health.component.spec.ts.mustache b/src/main/resources/generator/client/angular/admin/src/main/webapp/app/admin/health/health.component.spec.ts.mustache
index 1be0af988..581ec2cef 100644
--- a/src/main/resources/generator/client/angular/admin/src/main/webapp/app/admin/health/health.component.spec.ts.mustache
+++ b/src/main/resources/generator/client/angular/admin/src/main/webapp/app/admin/health/health.component.spec.ts.mustache
@@ -73,13 +73,13 @@ describe('HealthComponent', () => {
     it('should get success badge class', () => {
       const upBadgeClass = comp.getBadgeClass('UP');
 
-      expect(upBadgeClass).toEqual('bg-success');
+      expect(upBadgeClass).toBe('bg-success');
     });
 
     it('should get danger badge class', () => {
       const downBadgeClass = comp.getBadgeClass('DOWN');
 
-      expect(downBadgeClass).toEqual('bg-danger');
+      expect(downBadgeClass).toBe('bg-danger');
     });
   });
 });
diff --git a/src/main/resources/generator/client/angular/admin/src/main/webapp/app/admin/health/modal/health-modal.component.spec.ts.mustache b/src/main/resources/generator/client/angular/admin/src/main/webapp/app/admin/health/modal/health-modal.component.spec.ts.mustache
index 571a2cc20..080c17fdb 100644
--- a/src/main/resources/generator/client/angular/admin/src/main/webapp/app/admin/health/modal/health-modal.component.spec.ts.mustache
+++ b/src/main/resources/generator/client/angular/admin/src/main/webapp/app/admin/health/modal/health-modal.component.spec.ts.mustache
@@ -29,7 +29,7 @@ describe('HealthModalComponent', () => {
 
       const result = comp.readableValue({ name: 'jhipster' });
 
-      expect(result).toEqual('{"name":"jhipster"}');
+      expect(result).toBe('{"name":"jhipster"}');
     });
 
     it('should return string value', () => {
@@ -40,7 +40,7 @@ describe('HealthModalComponent', () => {
 
       const result = comp.readableValue('jhipster');
 
-      expect(result).toEqual('jhipster');
+      expect(result).toBe('jhipster');
     });
 
     it('should return storage space in a human readable unit (GB)', () => {
@@ -51,7 +51,7 @@ describe('HealthModalComponent', () => {
 
       const result = comp.readableValue(1073741825);
 
-      expect(result).toEqual('1.00 GB');
+      expect(result).toBe('1.00 GB');
     });
 
     it('should return storage space in a human readable unit (MB)', () => {
@@ -62,7 +62,7 @@ describe('HealthModalComponent', () => {
 
       const result = comp.readableValue(1073741824);
 
-      expect(result).toEqual('1024.00 MB');
+      expect(result).toBe('1024.00 MB');
     });
 
     it('should return string value', () => {
@@ -73,7 +73,7 @@ describe('HealthModalComponent', () => {
 
       const result = comp.readableValue(1234);
 
-      expect(result).toEqual('1234');
+      expect(result).toBe('1234');
     });
   });
 });
diff --git a/src/main/resources/generator/client/angular/admin/src/main/webapp/app/config/application-config.service.spec.ts.mustache b/src/main/resources/generator/client/angular/admin/src/main/webapp/app/config/application-config.service.spec.ts.mustache
index 0fc3c1d89..c5dd6c35a 100644
--- a/src/main/resources/generator/client/angular/admin/src/main/webapp/app/config/application-config.service.spec.ts.mustache
+++ b/src/main/resources/generator/client/angular/admin/src/main/webapp/app/config/application-config.service.spec.ts.mustache
@@ -12,7 +12,7 @@ describe('ApplicationConfigService', () => {
 
   describe('without prefix', () => {
     it('should return correctly', () => {
-      expect(service.getEndpointFor('api')).toEqual('api');
+      expect(service.getEndpointFor('api')).toBe('api');
     });
   });
 
@@ -22,7 +22,7 @@ describe('ApplicationConfigService', () => {
     });
 
     it('should return correctly', () => {
-      expect(service.getEndpointFor('api')).toEqual('prefix/api');
+      expect(service.getEndpointFor('api')).toBe('prefix/api');
     });
   });
 });
diff --git a/src/main/resources/generator/client/angular/core/src/main/webapp/app/app.component.spec.ts.mustache b/src/main/resources/generator/client/angular/core/src/main/webapp/app/app.component.spec.ts.mustache
index b8152351a..de2b31404 100644
--- a/src/main/resources/generator/client/angular/core/src/main/webapp/app/app.component.spec.ts.mustache
+++ b/src/main/resources/generator/client/angular/core/src/main/webapp/app/app.component.spec.ts.mustache
@@ -20,7 +20,7 @@ describe('App Component', () => {
 
   describe('ngOnInit', () => {
     it('should have appName', () => {
-      expect(comp.appName()).toEqual('{{baseName}}');
+      expect(comp.appName()).toBe('{{baseName}}');
     });
   });
 });
diff --git a/src/main/resources/generator/client/angular/security/jwt/src/main/webapp/app/login/login.component.spec.ts.mustache b/src/main/resources/generator/client/angular/security/jwt/src/main/webapp/app/login/login.component.spec.ts.mustache
index c426e5db7..639a429a8 100644
--- a/src/main/resources/generator/client/angular/security/jwt/src/main/webapp/app/login/login.component.spec.ts.mustache
+++ b/src/main/resources/generator/client/angular/security/jwt/src/main/webapp/app/login/login.component.spec.ts.mustache
@@ -92,7 +92,7 @@ describe('Login Component', () => {
 
       comp.login();
 
-      expect(comp.errorMessage()).toEqual('Authentication failed');
+      expect(comp.errorMessage()).toBe('Authentication failed');
     });
   });
 
diff --git a/src/main/resources/generator/client/angular/security/oauth2/src/main/webapp/app/auth/http-auth.interceptor.spec.ts.mustache b/src/main/resources/generator/client/angular/security/oauth2/src/main/webapp/app/auth/http-auth.interceptor.spec.ts.mustache
index 3af799378..0f8cca7d8 100644
--- a/src/main/resources/generator/client/angular/security/oauth2/src/main/webapp/app/auth/http-auth.interceptor.spec.ts.mustache
+++ b/src/main/resources/generator/client/angular/security/oauth2/src/main/webapp/app/auth/http-auth.interceptor.spec.ts.mustache
@@ -40,7 +40,7 @@ describe('httpAuthInterceptor', () => {
       const req = httpTestingController.expectOne(originalRequest.url);
       expect(req.request.method).toEqual(HTTP_METHOD);
       expect(req.request.url).toEqual(URL);
-      expect(req.request.headers.get('ContentType')).toEqual('application/json');
+      expect(req.request.headers.get('ContentType')).toBe('application/json');
       expect(req.request.headers.get('Authorization')).toEqual(`Bearer ${TOKEN}`);
     });
 
@@ -51,7 +51,7 @@ describe('httpAuthInterceptor', () => {
       httpClient.request(originalRequest).subscribe();
 
       const req = httpTestingController.expectOne(originalRequest.url);
-      expect(req.request.headers.get('ContentType')).toEqual('application/json');
+      expect(req.request.headers.get('ContentType')).toBe('application/json');
       expect(req.request.headers.get('Authorization')).toBeFalsy();
     });
   });
diff --git a/src/main/resources/generator/client/common/i18n/i18n.spec.ts b/src/main/resources/generator/client/common/i18n/i18n.spec.ts
index 326c93a96..f837218e0 100644
--- a/src/main/resources/generator/client/common/i18n/i18n.spec.ts
+++ b/src/main/resources/generator/client/common/i18n/i18n.spec.ts
@@ -3,11 +3,11 @@ import { mergeTranslations } from '@/Translations';
 
 describe('i18n configuration', () => {
   it('loads en translation', () => {
-    expect(i18n.getResourceBundle('en', '')['home']['translationEnabled']).toEqual('Internationalization enabled');
+    expect(i18n.getResourceBundle('en', '')['home']['translationEnabled']).toBe('Internationalization enabled');
   });
 
   it('loads fr translation', () => {
-    expect(i18n.getResourceBundle('fr', '')['home']['translationEnabled']).toEqual('Internationalisation activée');
+    expect(i18n.getResourceBundle('fr', '')['home']['translationEnabled']).toBe('Internationalisation activée');
   });
 
   describe('mergeTranslations function', () => {
diff --git a/src/main/resources/generator/server/springboot/database/datasource/MsSQLTestContainerExtension.java.mustache b/src/main/resources/generator/server/springboot/database/common/MsSQLTestContainerExtension.java.mustache
similarity index 100%
rename from src/main/resources/generator/server/springboot/database/datasource/MsSQLTestContainerExtension.java.mustache
rename to src/main/resources/generator/server/springboot/database/common/MsSQLTestContainerExtension.java.mustache
diff --git a/src/main/resources/generator/server/springboot/database/datasource/databaseType.md.mustache b/src/main/resources/generator/server/springboot/database/common/databaseType.md.mustache
similarity index 100%
rename from src/main/resources/generator/server/springboot/database/datasource/databaseType.md.mustache
rename to src/main/resources/generator/server/springboot/database/common/databaseType.md.mustache
diff --git a/src/main/resources/generator/server/springboot/database/datasource/docker/container-license-acceptance.txt.mustache b/src/main/resources/generator/server/springboot/database/common/docker/container-license-acceptance.txt.mustache
similarity index 100%
rename from src/main/resources/generator/server/springboot/database/datasource/docker/container-license-acceptance.txt.mustache
rename to src/main/resources/generator/server/springboot/database/common/docker/container-license-acceptance.txt.mustache
diff --git a/src/main/resources/generator/server/springboot/database/datasource/docker/mariadb.yml.mustache b/src/main/resources/generator/server/springboot/database/common/docker/mariadb.yml.mustache
similarity index 100%
rename from src/main/resources/generator/server/springboot/database/datasource/docker/mariadb.yml.mustache
rename to src/main/resources/generator/server/springboot/database/common/docker/mariadb.yml.mustache
diff --git a/src/main/resources/generator/server/springboot/database/datasource/docker/mssql.yml.mustache b/src/main/resources/generator/server/springboot/database/common/docker/mssql.yml.mustache
similarity index 100%
rename from src/main/resources/generator/server/springboot/database/datasource/docker/mssql.yml.mustache
rename to src/main/resources/generator/server/springboot/database/common/docker/mssql.yml.mustache
diff --git a/src/main/resources/generator/server/springboot/database/datasource/docker/mysql.yml.mustache b/src/main/resources/generator/server/springboot/database/common/docker/mysql.yml.mustache
similarity index 100%
rename from src/main/resources/generator/server/springboot/database/datasource/docker/mysql.yml.mustache
rename to src/main/resources/generator/server/springboot/database/common/docker/mysql.yml.mustache
diff --git a/src/main/resources/generator/server/springboot/database/datasource/docker/postgresql.yml.mustache b/src/main/resources/generator/server/springboot/database/common/docker/postgresql.yml.mustache
similarity index 100%
rename from src/main/resources/generator/server/springboot/database/datasource/docker/postgresql.yml.mustache
rename to src/main/resources/generator/server/springboot/database/common/docker/postgresql.yml.mustache
diff --git a/src/main/resources/generator/server/springboot/database/jpa/DatabaseConfiguration.java.mustache b/src/main/resources/generator/server/springboot/database/jpa/DatabaseConfiguration.java.mustache
index f294bfeb2..584a526d0 100644
--- a/src/main/resources/generator/server/springboot/database/jpa/DatabaseConfiguration.java.mustache
+++ b/src/main/resources/generator/server/springboot/database/jpa/DatabaseConfiguration.java.mustache
@@ -1,4 +1,4 @@
-package {{packageName}}.wire.database.infrastructure.secondary;
+package {{packageName}}.wire.{{databaseType}}.infrastructure.secondary;
 
 import org.springframework.context.annotation.Configuration;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;


Test patch:
diff --git a/src/main/resources/generator/client/react/security/jwt/src/test/webapp/unit/login/primary/loginForm/index.test.tsx.mustache b/src/main/resources/generator/client/react/security/jwt/src/test/webapp/unit/login/primary/loginForm/index.test.tsx.mustache
index 3cac88559..cbc45166d 100644
--- a/src/main/resources/generator/client/react/security/jwt/src/test/webapp/unit/login/primary/loginForm/index.test.tsx.mustache
+++ b/src/main/resources/generator/client/react/security/jwt/src/test/webapp/unit/login/primary/loginForm/index.test.tsx.mustache
@@ -49,7 +49,7 @@ describe('loginForm', () => {
     const spy = mockPost();
     await login();
 
-    expect(spy).toHaveBeenCalledTimes(1);
+    expect(spy).toHaveBeenCalledOnce();
   });
 
   it('should display Log out after login and display Log in after logout', async () => {
diff --git a/src/main/resources/generator/client/react/security/jwt/src/test/webapp/unit/login/primary/loginModal/index.test.tsx.mustache b/src/main/resources/generator/client/react/security/jwt/src/test/webapp/unit/login/primary/loginModal/index.test.tsx.mustache
index 1eb9523bd..1bc396e21 100644
--- a/src/main/resources/generator/client/react/security/jwt/src/test/webapp/unit/login/primary/loginModal/index.test.tsx.mustache
+++ b/src/main/resources/generator/client/react/security/jwt/src/test/webapp/unit/login/primary/loginModal/index.test.tsx.mustache
@@ -68,7 +68,7 @@ describe('test login modal', () => {
       const submitButton = getByTestId('submit-button');
       fireEvent.click(submitButton);
     });
-    expect(spy).toHaveBeenCalledTimes(1);
+    expect(spy).toHaveBeenCalledOnce();
   });
 
   it('render the modal on login button click and close the modal on close button', async () => {
@@ -85,7 +85,7 @@ describe('test login modal', () => {
       const submitButton = getByRole('button', { name: 'Close' });
       fireEvent.click(submitButton);
     });
-    expect(spy).toHaveBeenCalledTimes(0);
+    expect(spy).not.toHaveBeenCalled();
   });
 
   it('should contain error message when submit button is clicked with empty value', async () => {
diff --git a/src/test/features/server/springboot/database/datasource.feature b/src/test/features/server/springboot/database/datasource.feature
deleted file mode 100644
index 554610389..000000000
--- a/src/test/features/server/springboot/database/datasource.feature
+++ /dev/null
@@ -1,97 +0,0 @@
-Feature: Datasource modules
-
-  Scenario: Should add PostgreSQL elements using legacy url
-    When I apply modules to default project
-      | maven-java            |
-      | spring-boot           |
-      | datasource-postgresql |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | postgresql.md |
-    And I should have files in "src/main/docker"
-      | postgresql.yml |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-    And I should have files in "src/test/resources/config"
-      | application-test.yml |
-
-  Scenario: Should get PostgreSQL module properties definition
-    When I get module "datasource-postgresql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MariaDB elements using legacy url
-    When I apply modules to default project
-      | maven-java         |
-      | spring-boot        |
-      | datasource-mariadb |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mariadb.md |
-    And I should have files in "src/main/docker"
-      | mariadb.yml |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-    And I should have files in "src/test/resources/config"
-      | application-test.yml |
-
-  Scenario: Should get MariaDB module properties definition
-    When I get module "datasource-mariadb" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MySQL elements using legacy url
-    When I apply modules to default project
-      | maven-java       |
-      | spring-boot      |
-      | datasource-mysql |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mysql.md |
-    And I should have files in "src/main/docker"
-      | mysql.yml |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-    And I should have files in "src/test/resources/config"
-      | application-test.yml |
-
-  Scenario: Should get MySQL module properties definition
-    When I get module "datasource-mysql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MsSQL elements using legacy url
-    When I apply modules to default project
-      | maven-java       |
-      | spring-boot      |
-      | datasource-mssql |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mssql.md |
-    And I should have files in "src/main/docker"
-      | mssql.yml |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-    And I should have files in "src/test/resources/config"
-      | application-test.yml |
-
-  Scenario: Should get MsSQL module properties definition
-    When I get module "datasource-mssql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
diff --git a/src/test/features/server/springboot/database/jooq-mariadb.feature b/src/test/features/server/springboot/database/jooq-mariadb.feature
new file mode 100644
index 000000000..7fcf3cc0f
--- /dev/null
+++ b/src/test/features/server/springboot/database/jooq-mariadb.feature
@@ -0,0 +1,41 @@
+Feature: Jooq MariaDB module
+
+  Scenario: Should add MariaDB elements using legacy url
+    When I apply modules to default project
+      | maven-java   |
+      | spring-boot  |
+      | jooq-mariadb |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mariadb.md |
+    And I should have files in "src/main/docker"
+      | mariadb.yml |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
+
+  Scenario: Should get MariaDB module properties definition
+    When I get module "jooq-mariadb" properties definition
+    Then I should have properties definitions
+      | Key                       | Type    | Mandatory |
+      | packageName               | STRING  | true      |
+      | baseName                  | STRING  | true      |
+      | indentSize                | INTEGER | false     |
+      | springConfigurationFormat | STRING  | false     |
+
+  Scenario: Should add MariaDB elements using module url
+    When I apply "jooq-mariadb" module to default project with maven file
+      | packageName | tech.jhipster.chips |
+      | baseName    | jhipster            |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mariadb.md |
+    And I should have files in "src/main/docker"
+      | mariadb.yml |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
diff --git a/src/test/features/server/springboot/database/jooq-mssql.feature b/src/test/features/server/springboot/database/jooq-mssql.feature
new file mode 100644
index 000000000..5c430b284
--- /dev/null
+++ b/src/test/features/server/springboot/database/jooq-mssql.feature
@@ -0,0 +1,30 @@
+Feature: Jooq MsSql module
+
+  Scenario: Should add MsSQL elements using legacy url
+    When I apply modules to default project
+      | maven-java  |
+      | spring-boot |
+      | jooq-mssql  |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mssql.md |
+    And I should have files in "src/main/docker"
+      | mssql.yml |
+    And I should have files in "src/test/java/tech/jhipster/chips"
+      | MsSQLTestContainerExtension.java |
+    And I should have files in "src/test/resources"
+      | container-license-acceptance.txt |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
+
+  Scenario: Should get MsSQL module properties definition
+    When I get module "jooq-mssql" properties definition
+    Then I should have properties definitions
+      | Key                       | Type    | Mandatory |
+      | packageName               | STRING  | true      |
+      | baseName                  | STRING  | true      |
+      | indentSize                | INTEGER | false     |
+      | springConfigurationFormat | STRING  | false     |
diff --git a/src/test/features/server/springboot/database/jooq-mysql.feature b/src/test/features/server/springboot/database/jooq-mysql.feature
new file mode 100644
index 000000000..3d597ef3e
--- /dev/null
+++ b/src/test/features/server/springboot/database/jooq-mysql.feature
@@ -0,0 +1,41 @@
+Feature: Jooq MySQL module
+
+  Scenario: Should add MySQL elements using legacy url
+    When I apply modules to default project
+      | maven-java  |
+      | spring-boot |
+      | jooq-mysql  |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mysql.md |
+    And I should have files in "src/main/docker"
+      | mysql.yml |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
+
+  Scenario: Should get MySQL module properties definition
+    When I get module "jooq-mysql" properties definition
+    Then I should have properties definitions
+      | Key                       | Type    | Mandatory |
+      | packageName               | STRING  | true      |
+      | baseName                  | STRING  | true      |
+      | indentSize                | INTEGER | false     |
+      | springConfigurationFormat | STRING  | false     |
+
+  Scenario: Should add MySQL elements using module url
+    When I apply "jooq-mysql" module to default project with maven file
+      | packageName | tech.jhipster.chips |
+      | baseName    | jhipster            |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mysql.md |
+    And I should have files in "src/main/docker"
+      | mysql.yml |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
diff --git a/src/test/features/server/springboot/database/jooq-postgresql.feature b/src/test/features/server/springboot/database/jooq-postgresql.feature
new file mode 100644
index 000000000..d4b6c46fd
--- /dev/null
+++ b/src/test/features/server/springboot/database/jooq-postgresql.feature
@@ -0,0 +1,41 @@
+Feature: Jooq PostgreSQL module
+
+  Scenario: Should add postgreSQL elements using legacy url
+    When I apply modules to default project
+      | maven-java      |
+      | spring-boot     |
+      | jooq-postgresql |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | postgresql.md |
+    And I should have files in "src/main/docker"
+      | postgresql.yml |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
+
+  Scenario: Should get postgreSQL module properties definition
+    When I get module "jooq-postgresql" properties definition
+    Then I should have properties definitions
+      | Key                       | Type    | Mandatory |
+      | packageName               | STRING  | true      |
+      | baseName                  | STRING  | true      |
+      | indentSize                | INTEGER | false     |
+      | springConfigurationFormat | STRING  | false     |
+
+  Scenario: Should add postgreSQL elements using module url
+    When I apply "jooq-postgresql" module to default project with maven file
+      | packageName | tech.jhipster.chips |
+      | baseName    | jhipster            |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | postgresql.md |
+    And I should have files in "src/main/docker"
+      | postgresql.yml |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
diff --git a/src/test/features/server/springboot/database/jooq.feature b/src/test/features/server/springboot/database/jooq.feature
deleted file mode 100644
index 2f07fa8d1..000000000
--- a/src/test/features/server/springboot/database/jooq.feature
+++ /dev/null
@@ -1,109 +0,0 @@
-Feature: Jooq modules
-
-  Scenario: Should add PostgreSQL elements using legacy url
-    When I apply modules to default project
-      | maven-java            |
-      | spring-boot           |
-      | datasource-postgresql |
-      | jooq-postgresql       |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | postgresql.md |
-    And I should have files in "src/main/docker"
-      | postgresql.yml |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-    And I should have files in "src/test/resources/config"
-      | application-test.yml |
-
-  Scenario: Should get PostgreSQL module properties definition
-    When I get module "jooq-postgresql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | packageName               | STRING  | true      |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MariaDB elements using legacy url
-    When I apply modules to default project
-      | maven-java         |
-      | spring-boot        |
-      | datasource-mariadb |
-      | jooq-mariadb       |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mariadb.md |
-    And I should have files in "src/main/docker"
-      | mariadb.yml |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-    And I should have files in "src/test/resources/config"
-      | application-test.yml |
-
-  Scenario: Should get MariaDB module properties definition
-    When I get module "jooq-mariadb" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | packageName               | STRING  | true      |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MySQL elements using legacy url
-    When I apply modules to default project
-      | maven-java       |
-      | spring-boot      |
-      | datasource-mysql |
-      | jooq-mysql       |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mysql.md |
-    And I should have files in "src/main/docker"
-      | mysql.yml |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-    And I should have files in "src/test/resources/config"
-      | application-test.yml |
-
-  Scenario: Should get MySQL module properties definition
-    When I get module "jooq-mysql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | packageName               | STRING  | true      |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MsSQL elements using legacy url
-    When I apply modules to default project
-      | maven-java       |
-      | spring-boot      |
-      | datasource-mssql |
-      | jooq-mssql       |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mssql.md |
-    And I should have files in "src/main/docker"
-      | mssql.yml |
-    And I should have files in "src/test/java/tech/jhipster/chips"
-      | MsSQLTestContainerExtension.java |
-    And I should have files in "src/test/resources"
-      | container-license-acceptance.txt |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-    And I should have files in "src/test/resources/config"
-      | application-test.yml |
-
-  Scenario: Should get MsSQL module properties definition
-    When I get module "jooq-mssql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | packageName               | STRING  | true      |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
diff --git a/src/test/features/server/springboot/database/jpa-mariadb.feature b/src/test/features/server/springboot/database/jpa-mariadb.feature
new file mode 100644
index 000000000..457497aa3
--- /dev/null
+++ b/src/test/features/server/springboot/database/jpa-mariadb.feature
@@ -0,0 +1,45 @@
+Feature: JPA MariaDB module
+
+  Scenario: Should add MariaDB elements using legacy url
+    When I apply modules to default project
+      | maven-java  |
+      | spring-boot |
+      | jpa-mariadb |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mariadb.md |
+    And I should have files in "src/main/docker"
+      | mariadb.yml |
+    And I should have files in "src/main/java/tech/jhipster/chips/wire/mariadb/infrastructure/secondary"
+      | DatabaseConfiguration.java |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
+
+  Scenario: Should get MariaDB module properties definition
+    When I get module "jpa-mariadb" properties definition
+    Then I should have properties definitions
+      | Key                       | Type    | Mandatory |
+      | packageName               | STRING  | true      |
+      | baseName                  | STRING  | true      |
+      | indentSize                | INTEGER | false     |
+      | springConfigurationFormat | STRING  | false     |
+
+  Scenario: Should add MariaDB elements using module url
+    When I apply "jpa-mariadb" module to default project with maven file
+      | packageName | tech.jhipster.chips |
+      | baseName    | jhipster            |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mariadb.md |
+    And I should have files in "src/main/docker"
+      | mariadb.yml |
+    And I should have files in "src/main/java/tech/jhipster/chips/wire/mariadb/infrastructure/secondary"
+      | DatabaseConfiguration.java |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
diff --git a/src/test/features/server/springboot/database/jpa-mssql.feature b/src/test/features/server/springboot/database/jpa-mssql.feature
new file mode 100644
index 000000000..880f28c11
--- /dev/null
+++ b/src/test/features/server/springboot/database/jpa-mssql.feature
@@ -0,0 +1,32 @@
+Feature: JPA MsSql module
+
+  Scenario: Should add MsSQL elements using legacy url
+    When I apply modules to default project
+      | maven-java  |
+      | spring-boot |
+      | jpa-mssql   |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mssql.md |
+    And I should have files in "src/main/docker"
+      | mssql.yml |
+    And I should have files in "src/main/java/tech/jhipster/chips/wire/mssql/infrastructure/secondary"
+      | DatabaseConfiguration.java |
+    And I should have files in "src/test/java/tech/jhipster/chips"
+      | MsSQLTestContainerExtension.java |
+    And I should have files in "src/test/resources"
+      | container-license-acceptance.txt |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
+
+  Scenario: Should get MsSQL module properties definition
+    When I get module "jpa-mssql" properties definition
+    Then I should have properties definitions
+      | Key                       | Type    | Mandatory |
+      | packageName               | STRING  | true      |
+      | baseName                  | STRING  | true      |
+      | indentSize                | INTEGER | false     |
+      | springConfigurationFormat | STRING  | false     |
diff --git a/src/test/features/server/springboot/database/jpa-mysql.feature b/src/test/features/server/springboot/database/jpa-mysql.feature
new file mode 100644
index 000000000..eeaa0064b
--- /dev/null
+++ b/src/test/features/server/springboot/database/jpa-mysql.feature
@@ -0,0 +1,45 @@
+Feature: JPA MySQL module
+
+  Scenario: Should add MySQL elements using legacy url
+    When I apply modules to default project
+      | maven-java  |
+      | spring-boot |
+      | jpa-mysql   |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mysql.md |
+    And I should have files in "src/main/docker"
+      | mysql.yml |
+    And I should have files in "src/main/java/tech/jhipster/chips/wire/mysql/infrastructure/secondary"
+      | DatabaseConfiguration.java |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
+
+  Scenario: Should get MySQL module properties definition
+    When I get module "jpa-mysql" properties definition
+    Then I should have properties definitions
+      | Key                       | Type    | Mandatory |
+      | packageName               | STRING  | true      |
+      | baseName                  | STRING  | true      |
+      | indentSize                | INTEGER | false     |
+      | springConfigurationFormat | STRING  | false     |
+
+  Scenario: Should add MySQL elements using module url
+    When I apply "jpa-mysql" module to default project with maven file
+      | packageName | tech.jhipster.chips |
+      | baseName    | jhipster            |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | mysql.md |
+    And I should have files in "src/main/docker"
+      | mysql.yml |
+    And I should have files in "src/main/java/tech/jhipster/chips/wire/mysql/infrastructure/secondary"
+      | DatabaseConfiguration.java |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
diff --git a/src/test/features/server/springboot/database/jpa-postgresql.feature b/src/test/features/server/springboot/database/jpa-postgresql.feature
new file mode 100644
index 000000000..320d55fda
--- /dev/null
+++ b/src/test/features/server/springboot/database/jpa-postgresql.feature
@@ -0,0 +1,45 @@
+Feature: JPA PostgreSQL module
+
+  Scenario: Should add postgreSQL elements using legacy url
+    When I apply modules to default project
+      | maven-java     |
+      | spring-boot    |
+      | jpa-postgresql |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | postgresql.md |
+    And I should have files in "src/main/docker"
+      | postgresql.yml |
+    And I should have files in "src/main/java/tech/jhipster/chips/wire/postgresql/infrastructure/secondary"
+      | DatabaseConfiguration.java |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
+
+  Scenario: Should get postgreSQL module properties definition
+    When I get module "jpa-postgresql" properties definition
+    Then I should have properties definitions
+      | Key                       | Type    | Mandatory |
+      | packageName               | STRING  | true      |
+      | baseName                  | STRING  | true      |
+      | indentSize                | INTEGER | false     |
+      | springConfigurationFormat | STRING  | false     |
+
+  Scenario: Should add postgreSQL elements using module url
+    When I apply "jpa-postgresql" module to default project with maven file
+      | packageName | tech.jhipster.chips |
+      | baseName    | jhipster            |
+    Then I should have files in ""
+      | pom.xml |
+    And I should have files in "documentation"
+      | postgresql.md |
+    And I should have files in "src/main/docker"
+      | postgresql.yml |
+    And I should have files in "src/main/java/tech/jhipster/chips/wire/postgresql/infrastructure/secondary"
+      | DatabaseConfiguration.java |
+    And I should have files in "src/main/resources/config"
+      | application.yml |
+    And I should have files in "src/test/resources/config"
+      | application-test.yml |
diff --git a/src/test/features/server/springboot/database/jpa.feature b/src/test/features/server/springboot/database/jpa.feature
deleted file mode 100644
index 9368b4e70..000000000
--- a/src/test/features/server/springboot/database/jpa.feature
+++ /dev/null
@@ -1,109 +0,0 @@
-Feature: JPA modules
-
-  Scenario: Should add PostgreSQL elements using legacy url
-    When I apply modules to default project
-      | maven-java            |
-      | spring-boot           |
-      | datasource-postgresql |
-      | jpa-postgresql        |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | postgresql.md |
-    And I should have files in "src/main/docker"
-      | postgresql.yml |
-    And I should have files in "src/main/java/tech/jhipster/chips/wire/database/infrastructure/secondary"
-      | DatabaseConfiguration.java |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-
-  Scenario: Should get PostgreSQL module properties definition
-    When I get module "jpa-postgresql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | packageName               | STRING  | true      |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MariaDB elements using legacy url
-    When I apply modules to default project
-      | maven-java         |
-      | spring-boot        |
-      | datasource-mariadb |
-      | jpa-mariadb        |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mariadb.md |
-    And I should have files in "src/main/docker"
-      | mariadb.yml |
-    And I should have files in "src/main/java/tech/jhipster/chips/wire/database/infrastructure/secondary"
-      | DatabaseConfiguration.java |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-
-  Scenario: Should get MariaDB module properties definition
-    When I get module "jpa-mariadb" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | packageName               | STRING  | true      |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MySQL elements using legacy url
-    When I apply modules to default project
-      | maven-java       |
-      | spring-boot      |
-      | datasource-mysql |
-      | jpa-mysql        |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mysql.md |
-    And I should have files in "src/main/docker"
-      | mysql.yml |
-    And I should have files in "src/main/java/tech/jhipster/chips/wire/database/infrastructure/secondary"
-      | DatabaseConfiguration.java |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-
-  Scenario: Should get MySQL module properties definition
-    When I get module "jpa-mysql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | packageName               | STRING  | true      |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
-
-  Scenario: Should add MsSQL elements using legacy url
-    When I apply modules to default project
-      | maven-java       |
-      | spring-boot      |
-      | datasource-mssql |
-      | jpa-mssql        |
-    Then I should have files in ""
-      | pom.xml |
-    And I should have files in "documentation"
-      | mssql.md |
-    And I should have files in "src/main/docker"
-      | mssql.yml |
-    And I should have files in "src/main/java/tech/jhipster/chips/wire/database/infrastructure/secondary"
-      | DatabaseConfiguration.java |
-    And I should have files in "src/test/java/tech/jhipster/chips"
-      | MsSQLTestContainerExtension.java |
-    And I should have files in "src/test/resources"
-      | container-license-acceptance.txt |
-    And I should have files in "src/main/resources/config"
-      | application.yml |
-
-  Scenario: Should get MsSQL module properties definition
-    When I get module "jpa-mssql" properties definition
-    Then I should have properties definitions
-      | Key                       | Type    | Mandatory |
-      | packageName               | STRING  | true      |
-      | baseName                  | STRING  | true      |
-      | indentSize                | INTEGER | false     |
-      | springConfigurationFormat | STRING  | false     |
diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceModuleFactoryTest.java
deleted file mode 100644
index 813c3798e..000000000
--- a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/datasource/domain/DatasourceModuleFactoryTest.java
+++ /dev/null
@@ -1,290 +0,0 @@
-package tech.jhipster.lite.generator.server.springboot.database.datasource.domain;
-
-import static org.mockito.Mockito.when;
-import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.assertThatModuleWithFiles;
-import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.file;
-import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.pomFile;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import tech.jhipster.lite.TestFileUtils;
-import tech.jhipster.lite.UnitTest;
-import tech.jhipster.lite.module.domain.JHipsterModule;
-import tech.jhipster.lite.module.domain.JHipsterModulesFixture;
-import tech.jhipster.lite.module.domain.docker.DockerImageName;
-import tech.jhipster.lite.module.domain.docker.DockerImageVersion;
-import tech.jhipster.lite.module.domain.docker.DockerImages;
-import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
-import tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions;
-
-@UnitTest
-@ExtendWith(MockitoExtension.class)
-class DatasourceModuleFactoryTest {
-
-  @Mock
-  private DockerImages dockerImages;
-
-  @InjectMocks
-  private DatasourceModuleFactory factory;
-
-  @Test
-  void shouldCreatePostgresqlModule() {
-    JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest())
-      .basePackage("tech.jhipster.jhlitest")
-      .projectBaseName("myapp")
-      .build();
-
-    when(dockerImages.get(new DockerImageName("postgres"))).thenReturn(new DockerImageVersion("postgres", "0.0.0"));
-
-    JHipsterModule module = factory.buildPostgresql(properties);
-
-    assertThatModuleWithFiles(module, pomFile())
-      .hasFile("documentation/postgresql.md")
-      .containing("docker compose -f src/main/docker/postgresql.yml up -d")
-      .and()
-      .hasFile("pom.xml")
-      .containing(
-        """
-            <dependency>
-              <groupId>org.postgresql</groupId>
-              <artifactId>postgresql</artifactId>
-              <scope>runtime</scope>
-            </dependency>
-        """
-      )
-      .containing("<groupId>com.zaxxer</groupId>")
-      .containing("<artifactId>HikariCP</artifactId>")
-      .containing("<groupId>org.testcontainers</groupId>")
-      .and()
-      .hasFile("src/main/resources/config/application.yml")
-      .containing(
-        """
-          datasource:
-            driver-class-name: org.postgresql.Driver
-            hikari:
-              auto-commit: false
-              poolName: Hikari
-            password: ''
-            type: com.zaxxer.hikari.HikariDataSource
-            url: jdbc:postgresql://localhost:5432/myapp
-            username: myapp
-        """
-      )
-      .and()
-      .hasFile("src/test/resources/config/application-test.yml")
-      .containing(
-        """
-        spring:
-          datasource:
-            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
-            hikari:
-              maximum-pool-size: 2
-            password: ''
-            url: jdbc:tc:postgresql:0.0.0:///myapp?TC_TMPFS=/testtmpfs:rw
-            username: myapp
-        """
-      );
-  }
-
-  @Test
-  void shouldCreateMariadbModule() {
-    JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest())
-      .basePackage("tech.jhipster.jhlitest")
-      .projectBaseName("myapp")
-      .build();
-
-    when(dockerImages.get(new DockerImageName("mariadb"))).thenReturn(new DockerImageVersion("mariadb", "0.0.0"));
-
-    JHipsterModule module = factory.buildMariaDB(properties);
-
-    assertThatModuleWithFiles(module, pomFile())
-      .hasFile("documentation/mariadb.md")
-      .containing("docker compose -f src/main/docker/mariadb.yml up -d")
-      .and()
-      .hasPrefixedFiles("src/main/docker", "mariadb.yml")
-      .hasFile("pom.xml")
-      .containing(
-        """
-            <dependency>
-              <groupId>org.mariadb.jdbc</groupId>
-              <artifactId>mariadb-java-client</artifactId>
-              <scope>runtime</scope>
-            </dependency>
-        """
-      )
-      .containing("<groupId>com.zaxxer</groupId>")
-      .containing("<artifactId>HikariCP</artifactId>")
-      .containing("<groupId>org.testcontainers</groupId>")
-      .containing("<artifactId>mariadb</artifactId>")
-      .and()
-      .hasFile("src/main/resources/config/application.yml")
-      .containing(
-        """
-        spring:
-          datasource:
-            driver-class-name: org.mariadb.jdbc.Driver
-            hikari:
-              auto-commit: false
-              poolName: Hikari
-            password: ''
-            type: com.zaxxer.hikari.HikariDataSource
-            url: jdbc:mariadb://localhost:3306/myapp
-            username: root
-        """
-      )
-      .and()
-      .hasFile("src/test/resources/config/application-test.yml")
-      .containing(
-        """
-        spring:
-          datasource:
-            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
-            hikari:
-              maximum-pool-size: 2
-            password: ''
-            url: jdbc:tc:mariadb:0.0.0:///myapp
-            username: myapp
-        """
-      );
-  }
-
-  @Test
-  void shouldCreateMysqlModule() {
-    JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest())
-      .basePackage("tech.jhipster.jhlitest")
-      .projectBaseName("myapp")
-      .build();
-
-    when(dockerImages.get(new DockerImageName("mysql"))).thenReturn(new DockerImageVersion("mysql", "0.0.0"));
-
-    JHipsterModule module = factory.buildMySQL(properties);
-
-    assertThatModuleWithFiles(module, pomFile())
-      .hasFile("documentation/mysql.md")
-      .containing("docker compose -f src/main/docker/mysql.yml up -d")
-      .and()
-      .hasPrefixedFiles("src/main/docker", "mysql.yml")
-      .hasFile("pom.xml")
-      .containing(
-        """
-            <dependency>
-              <groupId>com.mysql</groupId>
-              <artifactId>mysql-connector-j</artifactId>
-              <scope>runtime</scope>
-            </dependency>
-        """
-      )
-      .containing("<groupId>com.zaxxer</groupId>")
-      .containing("<artifactId>HikariCP</artifactId>")
-      .containing("<groupId>org.testcontainers</groupId>")
-      .containing("<artifactId>mysql</artifactId>")
-      .and()
-      .hasFile("src/main/resources/config/application.yml")
-      .containing(
-        // language=yaml
-        """
-        spring:
-          datasource:
-            driver-class-name: com.mysql.cj.jdbc.Driver
-            hikari:
-              auto-commit: false
-              poolName: Hikari
-            password: ''
-            type: com.zaxxer.hikari.HikariDataSource
-            url: jdbc:mysql://localhost:3306/myapp
-            username: root
-        """
-      )
-      .and()
-      .hasFile("src/test/resources/config/application-test.yml")
-      .containing(
-        // language=yaml
-        """
-        spring:
-          datasource:
-            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
-            hikari:
-              maximum-pool-size: 2
-            password: ''
-            url: jdbc:tc:mysql:0.0.0:///myapp
-            username: myapp
-        """
-      );
-  }
-
-  @Test
-  void shouldCreateMssqlModule() {
-    JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest())
-      .basePackage("tech.jhipster.jhlitest")
-      .projectBaseName("myapp")
-      .build();
-
-    when(dockerImages.get(new DockerImageName("mcr.microsoft.com/mssql/server"))).thenReturn(
-      new DockerImageVersion("mcr.microsoft.com/mssql/server", "0.0.0")
-    );
-
-    JHipsterModule module = factory.buildMsSQL(properties);
-
-    assertThatModuleWithFiles(module, pomFile(), integrationTestAnnotation())
-      .hasFile("documentation/mssql.md")
-      .containing("docker compose -f src/main/docker/mssql.yml up -d")
-      .and()
-      .hasFile("src/test/java/tech/jhipster/jhlitest/MsSQLTestContainerExtension.java")
-      .and()
-      .hasFile("src/test/resources/container-license-acceptance.txt")
-      .and()
-      .hasFile("pom.xml")
-      .containing(
-        """
-            <dependency>
-              <groupId>com.microsoft.sqlserver</groupId>
-              <artifactId>mssql-jdbc</artifactId>
-              <scope>runtime</scope>
-            </dependency>
-        """
-      )
-      .containing("<groupId>com.zaxxer</groupId>")
-      .containing("<artifactId>HikariCP</artifactId>")
-      .containing("<groupId>org.testcontainers</groupId>")
-      .containing("<artifactId>mssqlserver</artifactId>")
-      .and()
-      .hasFile("src/main/resources/config/application.yml")
-      .containing(
-        // language=yaml
-        """
-        spring:
-          datasource:
-            driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
-            hikari:
-              auto-commit: false
-              poolName: Hikari
-            password: yourStrong(!)Password
-            type: com.zaxxer.hikari.HikariDataSource
-            url: jdbc:sqlserver://localhost:1433;database=myapp;trustServerCertificate=true
-            username: SA
-        """
-      )
-      .and()
-      .hasFile("src/test/resources/config/application-test.yml")
-      .containing(
-        // language=yaml
-        """
-        spring:
-          datasource:
-            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
-            hikari:
-              maximum-pool-size: 2
-            password: yourStrong(!)Password
-            url: jdbc:tc:sqlserver:///;database=myapp;trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw
-            username: SA
-        """
-      );
-  }
-
-  private JHipsterModulesAssertions.ModuleFile integrationTestAnnotation() {
-    return file("src/test/resources/projects/files/IntegrationTest.java", "src/test/java/tech/jhipster/jhlitest/IntegrationTest.java");
-  }
-}
diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleFactoryTest.java
index fcb5286e5..0773df34c 100644
--- a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleFactoryTest.java
+++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/jooq/domain/JooqModuleFactoryTest.java
@@ -1,19 +1,31 @@
 package tech.jhipster.lite.generator.server.springboot.database.jooq.domain;
 
-import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.assertThatModuleWithFiles;
-import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.pomFile;
+import static org.mockito.Mockito.when;
+import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.*;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
 import tech.jhipster.lite.TestFileUtils;
 import tech.jhipster.lite.UnitTest;
 import tech.jhipster.lite.module.domain.JHipsterModule;
 import tech.jhipster.lite.module.domain.JHipsterModulesFixture;
+import tech.jhipster.lite.module.domain.docker.DockerImageVersion;
+import tech.jhipster.lite.module.domain.docker.DockerImages;
 import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
+import tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions;
 
 @UnitTest
+@ExtendWith(MockitoExtension.class)
 class JooqModuleFactoryTest {
 
-  private final JooqModuleFactory factory = new JooqModuleFactory();
+  @Mock
+  private DockerImages dockerImages;
+
+  @InjectMocks
+  private JooqModuleFactory factory;
 
   @Test
   void shouldCreatePostgresqlModule() {
@@ -22,10 +34,26 @@ class JooqModuleFactoryTest {
       .projectBaseName("myapp")
       .build();
 
+    when(dockerImages.get("postgres")).thenReturn(new DockerImageVersion("postgres", "0.0.0"));
+
     JHipsterModule module = factory.buildPostgresql(properties);
 
     assertThatModuleWithFiles(module, pomFile())
+      .hasFile("documentation/postgresql.md")
+      .containing("docker compose -f src/main/docker/postgresql.yml up -d")
+      .and()
       .hasFile("pom.xml")
+      .containing(
+        """
+            <dependency>
+              <groupId>org.postgresql</groupId>
+              <artifactId>postgresql</artifactId>
+              <scope>runtime</scope>
+            </dependency>
+        """
+      )
+      .containing("<groupId>com.zaxxer</groupId>")
+      .containing("<artifactId>HikariCP</artifactId>")
       .containing(
         """
             <dependency>
@@ -34,40 +62,37 @@ class JooqModuleFactoryTest {
             </dependency>
         """
       )
+      .containing("<groupId>org.testcontainers</groupId>")
+      .containing("<artifactId>postgresql</artifactId>")
+      .containing("<artifactId>jooq-codegen-maven</artifactId>")
+      .and()
+      .hasFile("src/main/resources/config/application.yml")
+      .containing(
+        """
+        spring:
+          datasource:
+            driver-class-name: org.postgresql.Driver
+            hikari:
+              auto-commit: false
+              poolName: Hikari
+            password: ''
+            type: com.zaxxer.hikari.HikariDataSource
+            url: jdbc:postgresql://localhost:5432/myapp
+            username: myapp
+        """
+      )
+      .and()
+      .hasFile("src/test/resources/config/application-test.yml")
       .containing(
         """
-              <plugin>
-                <groupId>org.jooq</groupId>
-                <artifactId>jooq-codegen-maven</artifactId>
-                <version>${jooq.version}</version>
-                <executions>
-                  <execution>
-                    <id>jooq-codegen</id>
-                    <phase>generate-resources</phase>
-                    <goals>
-                      <goal>generate</goal>
-                    </goals>
-                  </execution>
-                </executions>
-                <configuration>
-                  <jdbc>
-                    <url>jdbc:postgresql://localhost:5432/myapp</url>
-                    <user>myapp</user>
-                    <password></password>
-                  </jdbc>
-                  <generator>
-                    <database>
-                      <name>org.jooq.meta.postgres.PostgresDatabase</name>
-                      <includes>.*</includes>
-                      <inputSchema>public</inputSchema>
-                    </database>
-                    <target>
-                      <packageName>org.jooq.codegen</packageName>
-                      <directory>target/generated-sources/jooq</directory>
-                    </target>
-                  </generator>
-                </configuration>
-              </plugin>
+        spring:
+          datasource:
+            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
+            hikari:
+              maximum-pool-size: 2
+            password: ''
+            url: jdbc:tc:postgresql:0.0.0:///myapp?TC_TMPFS=/testtmpfs:rw
+            username: myapp
         """
       );
   }
@@ -79,10 +104,27 @@ class JooqModuleFactoryTest {
       .projectBaseName("myapp")
       .build();
 
+    when(dockerImages.get("mariadb")).thenReturn(new DockerImageVersion("mariadb", "0.0.0"));
+
     JHipsterModule module = factory.buildMariaDB(properties);
 
     assertThatModuleWithFiles(module, pomFile())
+      .hasFile("documentation/mariadb.md")
+      .containing("docker compose -f src/main/docker/mariadb.yml up -d")
+      .and()
+      .hasPrefixedFiles("src/main/docker", "mariadb.yml")
       .hasFile("pom.xml")
+      .containing(
+        """
+            <dependency>
+              <groupId>org.mariadb.jdbc</groupId>
+              <artifactId>mariadb-java-client</artifactId>
+              <scope>runtime</scope>
+            </dependency>
+        """
+      )
+      .containing("<groupId>com.zaxxer</groupId>")
+      .containing("<artifactId>HikariCP</artifactId>")
       .containing(
         """
             <dependency>
@@ -91,40 +133,37 @@ class JooqModuleFactoryTest {
             </dependency>
         """
       )
+      .containing("<groupId>org.testcontainers</groupId>")
+      .containing("<artifactId>mariadb</artifactId>")
+      .containing("<artifactId>jooq-codegen-maven</artifactId>")
+      .and()
+      .hasFile("src/main/resources/config/application.yml")
+      .containing(
+        """
+        spring:
+          datasource:
+            driver-class-name: org.mariadb.jdbc.Driver
+            hikari:
+              auto-commit: false
+              poolName: Hikari
+            password: ''
+            type: com.zaxxer.hikari.HikariDataSource
+            url: jdbc:mariadb://localhost:3306/myapp
+            username: root
+        """
+      )
+      .and()
+      .hasFile("src/test/resources/config/application-test.yml")
       .containing(
         """
-              <plugin>
-                <groupId>org.jooq</groupId>
-                <artifactId>jooq-codegen-maven</artifactId>
-                <version>${jooq.version}</version>
-                <executions>
-                  <execution>
-                    <id>jooq-codegen</id>
-                    <phase>generate-resources</phase>
-                    <goals>
-                      <goal>generate</goal>
-                    </goals>
-                  </execution>
-                </executions>
-                <configuration>
-                  <jdbc>
-                    <url>jdbc:mariadb://localhost:3306/myapp</url>
-                    <user>root</user>
-                    <password></password>
-                  </jdbc>
-                  <generator>
-                    <database>
-                      <name>org.jooq.meta.mariadb.MariaDBDatabase</name>
-                      <includes>.*</includes>
-                      <inputSchema>myapp</inputSchema>
-                    </database>
-                    <target>
-                      <packageName>org.jooq.codegen</packageName>
-                      <directory>target/generated-sources/jooq</directory>
-                    </target>
-                  </generator>
-                </configuration>
-              </plugin>
+        spring:
+          datasource:
+            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
+            hikari:
+              maximum-pool-size: 2
+            password: ''
+            url: jdbc:tc:mariadb:0.0.0:///myapp
+            username: myapp
         """
       );
   }
@@ -136,10 +175,27 @@ class JooqModuleFactoryTest {
       .projectBaseName("myapp")
       .build();
 
+    when(dockerImages.get("mysql")).thenReturn(new DockerImageVersion("mysql", "0.0.0"));
+
     JHipsterModule module = factory.buildMySQL(properties);
 
     assertThatModuleWithFiles(module, pomFile())
+      .hasFile("documentation/mysql.md")
+      .containing("docker compose -f src/main/docker/mysql.yml up -d")
+      .and()
+      .hasPrefixedFiles("src/main/docker", "mysql.yml")
       .hasFile("pom.xml")
+      .containing(
+        """
+            <dependency>
+              <groupId>com.mysql</groupId>
+              <artifactId>mysql-connector-j</artifactId>
+              <scope>runtime</scope>
+            </dependency>
+        """
+      )
+      .containing("<groupId>com.zaxxer</groupId>")
+      .containing("<artifactId>HikariCP</artifactId>")
       .containing(
         """
             <dependency>
@@ -148,40 +204,39 @@ class JooqModuleFactoryTest {
             </dependency>
         """
       )
+      .containing("<groupId>org.testcontainers</groupId>")
+      .containing("<artifactId>mysql</artifactId>")
+      .containing("<artifactId>jooq-codegen-maven</artifactId>")
+      .and()
+      .hasFile("src/main/resources/config/application.yml")
       .containing(
+        // language=yaml
         """
-              <plugin>
-                <groupId>org.jooq</groupId>
-                <artifactId>jooq-codegen-maven</artifactId>
-                <version>${jooq.version}</version>
-                <executions>
-                  <execution>
-                    <id>jooq-codegen</id>
-                    <phase>generate-resources</phase>
-                    <goals>
-                      <goal>generate</goal>
-                    </goals>
-                  </execution>
-                </executions>
-                <configuration>
-                  <jdbc>
-                    <url>jdbc:mysql://localhost:3306/myapp</url>
-                    <user>root</user>
-                    <password></password>
-                  </jdbc>
-                  <generator>
-                    <database>
-                      <name>org.jooq.meta.mysql.MySQLDatabase</name>
-                      <includes>.*</includes>
-                      <inputSchema>myapp</inputSchema>
-                    </database>
-                    <target>
-                      <packageName>org.jooq.codegen</packageName>
-                      <directory>target/generated-sources/jooq</directory>
-                    </target>
-                  </generator>
-                </configuration>
-              </plugin>
+        spring:
+          datasource:
+            driver-class-name: com.mysql.cj.jdbc.Driver
+            hikari:
+              auto-commit: false
+              poolName: Hikari
+            password: ''
+            type: com.zaxxer.hikari.HikariDataSource
+            url: jdbc:mysql://localhost:3306/myapp
+            username: root
+        """
+      )
+      .and()
+      .hasFile("src/test/resources/config/application-test.yml")
+      .containing(
+        // language=yaml
+        """
+        spring:
+          datasource:
+            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
+            hikari:
+              maximum-pool-size: 2
+            password: ''
+            url: jdbc:tc:mysql:0.0.0:///myapp
+            username: myapp
         """
       );
   }
@@ -193,10 +248,30 @@ class JooqModuleFactoryTest {
       .projectBaseName("myapp")
       .build();
 
+    when(dockerImages.get("mcr.microsoft.com/mssql/server")).thenReturn(new DockerImageVersion("mcr.microsoft.com/mssql/server", "0.0.0"));
+
     JHipsterModule module = factory.buildMsSQL(properties);
 
-    assertThatModuleWithFiles(module, pomFile())
+    assertThatModuleWithFiles(module, pomFile(), integrationTestAnnotation())
+      .hasFile("documentation/mssql.md")
+      .containing("docker compose -f src/main/docker/mssql.yml up -d")
+      .and()
+      .hasFile("src/test/java/tech/jhipster/jhlitest/MsSQLTestContainerExtension.java")
+      .and()
+      .hasFile("src/test/resources/container-license-acceptance.txt")
+      .and()
       .hasFile("pom.xml")
+      .containing(
+        """
+            <dependency>
+              <groupId>com.microsoft.sqlserver</groupId>
+              <artifactId>mssql-jdbc</artifactId>
+              <scope>runtime</scope>
+            </dependency>
+        """
+      )
+      .containing("<groupId>com.zaxxer</groupId>")
+      .containing("<artifactId>HikariCP</artifactId>")
       .containing(
         """
             <dependency>
@@ -205,41 +280,44 @@ class JooqModuleFactoryTest {
             </dependency>
         """
       )
+      .containing("<groupId>org.testcontainers</groupId>")
+      .containing("<artifactId>mssqlserver</artifactId>")
+      .containing("<artifactId>jooq-codegen-maven</artifactId>")
+      .and()
+      .hasFile("src/main/resources/config/application.yml")
       .containing(
+        // language=yaml
         """
-              <plugin>
-                <groupId>org.jooq</groupId>
-                <artifactId>jooq-codegen-maven</artifactId>
-                <version>${jooq.version}</version>
-                <executions>
-                  <execution>
-                    <id>jooq-codegen</id>
-                    <phase>generate-resources</phase>
-                    <goals>
-                      <goal>generate</goal>
-                    </goals>
-                  </execution>
-                </executions>
-                <configuration>
-                  <jdbc>
-                    <url>jdbc:sqlserver://localhost:1433;database=myapp;trustServerCertificate=true</url>
-                    <user>SA</user>
-                    <password>yourStrong(!)Password</password>
-                  </jdbc>
-                  <generator>
-                    <database>
-                      <name>org.jooq.meta.sqlserver.SQLServerDatabase</name>
-                      <includes>.*</includes>
-                      <inputSchema>model</inputSchema>
-                    </database>
-                    <target>
-                      <packageName>org.jooq.codegen</packageName>
-                      <directory>target/generated-sources/jooq</directory>
-                    </target>
-                  </generator>
-                </configuration>
-              </plugin>
+        spring:
+          datasource:
+            driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+            hikari:
+              auto-commit: false
+              poolName: Hikari
+            password: yourStrong(!)Password
+            type: com.zaxxer.hikari.HikariDataSource
+            url: jdbc:sqlserver://localhost:1433;database=myapp;trustServerCertificate=true
+            username: SA
+        """
+      )
+      .and()
+      .hasFile("src/test/resources/config/application-test.yml")
+      .containing(
+        // language=yaml
+        """
+        spring:
+          datasource:
+            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
+            hikari:
+              maximum-pool-size: 2
+            password: yourStrong(!)Password
+            url: jdbc:tc:sqlserver:///;database=myapp;trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw
+            username: SA
         """
       );
   }
+
+  private JHipsterModulesAssertions.ModuleFile integrationTestAnnotation() {
+    return file("src/test/resources/projects/files/IntegrationTest.java", "src/test/java/tech/jhipster/jhlitest/IntegrationTest.java");
+  }
 }
diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/JpaModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/JpaModuleFactoryTest.java
index 36f267861..e4a2128b9 100644
--- a/src/test/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/JpaModuleFactoryTest.java
+++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/database/jpa/domain/JpaModuleFactoryTest.java
@@ -1,19 +1,33 @@
 package tech.jhipster.lite.generator.server.springboot.database.jpa.domain;
 
+import static org.mockito.Mockito.when;
 import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.assertThatModuleWithFiles;
+import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.file;
 import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.pomFile;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
 import tech.jhipster.lite.TestFileUtils;
 import tech.jhipster.lite.UnitTest;
 import tech.jhipster.lite.module.domain.JHipsterModule;
 import tech.jhipster.lite.module.domain.JHipsterModulesFixture;
+import tech.jhipster.lite.module.domain.docker.DockerImageVersion;
+import tech.jhipster.lite.module.domain.docker.DockerImages;
 import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
+import tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions;
 
 @UnitTest
+@ExtendWith(MockitoExtension.class)
 class JpaModuleFactoryTest {
 
-  private final JpaModuleFactory factory = new JpaModuleFactory();
+  @Mock
+  private DockerImages dockerImages;
+
+  @InjectMocks
+  private JpaModuleFactory factory;
 
   @Test
   void shouldCreatePostgresqlModule() {
@@ -22,25 +36,32 @@ class JpaModuleFactoryTest {
       .projectBaseName("myapp")
       .build();
 
+    when(dockerImages.get("postgres")).thenReturn(new DockerImageVersion("postgres", "0.0.0"));
+
     JHipsterModule module = factory.buildPostgresql(properties);
 
     assertThatModuleWithFiles(module, pomFile())
-      .hasFile("src/main/java/tech/jhipster/jhlitest/wire/database/infrastructure/secondary/DatabaseConfiguration.java")
-      .containing("package tech.jhipster.jhlitest.wire.database.infrastructure.secondary;")
+      .hasFile("src/main/java/tech/jhipster/jhlitest/wire/postgresql/infrastructure/secondary/DatabaseConfiguration.java")
+      .containing("package tech.jhipster.jhlitest.wire.postgresql.infrastructure.secondary;")
+      .and()
+      .hasFile("documentation/postgresql.md")
+      .containing("docker compose -f src/main/docker/postgresql.yml up -d")
       .and()
       .hasFile("pom.xml")
       .containing(
         """
-              <groupId>org.springframework.boot</groupId>
-              <artifactId>spring-boot-starter-data-jpa</artifactId>\
-        """
-      )
-      .containing(
-        """
-              <groupId>org.hibernate.orm</groupId>
-              <artifactId>hibernate-core</artifactId>\
+            <dependency>
+              <groupId>org.postgresql</groupId>
+              <artifactId>postgresql</artifactId>
+              <scope>runtime</scope>
+            </dependency>
         """
       )
+      .containing("<groupId>com.zaxxer</groupId>")
+      .containing("<artifactId>HikariCP</artifactId>")
+      .containing("<groupId>org.hibernate.orm</groupId>")
+      .containing("<artifactId>hibernate-core</artifactId>")
+      .containing("<groupId>org.testcontainers</groupId>")
       .and()
       .hasFile("src/main/resources/config/application.yml")
       .containing(
@@ -50,6 +71,15 @@ class JpaModuleFactoryTest {
             jpa:
               repositories:
                 bootstrap-mode: deferred
+          datasource:
+            driver-class-name: org.postgresql.Driver
+            hikari:
+              auto-commit: false
+              poolName: Hikari
+            password: ''
+            type: com.zaxxer.hikari.HikariDataSource
+            url: jdbc:postgresql://localhost:5432/myapp
+            username: myapp
           jpa:
             hibernate:
               ddl-auto: none
@@ -71,6 +101,20 @@ class JpaModuleFactoryTest {
                   fail_on_pagination_over_collection_fetch: true
                   in_clause_parameter_padding: true
         """
+      )
+      .and()
+      .hasFile("src/test/resources/config/application-test.yml")
+      .containing(
+        """
+        spring:
+          datasource:
+            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
+            hikari:
+              maximum-pool-size: 2
+            password: ''
+            url: jdbc:tc:postgresql:0.0.0:///myapp?TC_TMPFS=/testtmpfs:rw
+            username: myapp
+        """
       );
   }
 
@@ -81,25 +125,36 @@ class JpaModuleFactoryTest {
       .projectBaseName("myapp")
       .build();
 
+    when(dockerImages.get("mariadb")).thenReturn(new DockerImageVersion("mariadb", "0.0.0"));
+
     JHipsterModule module = factory.buildMariaDB(properties);
 
     assertThatModuleWithFiles(module, pomFile())
-      .hasFile("src/main/java/tech/jhipster/jhlitest/wire/database/infrastructure/secondary/DatabaseConfiguration.java")
-      .containing("package tech.jhipster.jhlitest.wire.database.infrastructure.secondary;")
+      .hasFile("documentation/mariadb.md")
+      .containing("docker compose -f src/main/docker/mariadb.yml up -d")
       .and()
+      .hasFile("src/main/java/tech/jhipster/jhlitest/wire/mariadb/infrastructure/secondary/DatabaseConfiguration.java")
+      .containing("package tech.jhipster.jhlitest.wire.mariadb.infrastructure.secondary;")
+      .and()
+      .hasPrefixedFiles("src/main/docker", "mariadb.yml")
       .hasFile("pom.xml")
+      .containing("<groupId>org.springframework.boot</groupId>")
+      .containing("<artifactId>spring-boot-starter-data-jpa</artifactId>")
       .containing(
         """
-              <groupId>org.springframework.boot</groupId>
-              <artifactId>spring-boot-starter-data-jpa</artifactId>\
-        """
-      )
-      .containing(
-        """
-              <groupId>org.hibernate.orm</groupId>
-              <artifactId>hibernate-core</artifactId>\
+            <dependency>
+              <groupId>org.mariadb.jdbc</groupId>
+              <artifactId>mariadb-java-client</artifactId>
+              <scope>runtime</scope>
+            </dependency>
         """
       )
+      .containing("<groupId>com.zaxxer</groupId>")
+      .containing("<artifactId>HikariCP</artifactId>")
+      .containing("<groupId>org.hibernate.orm</groupId>")
+      .containing("<artifactId>hibernate-core</artifactId>")
+      .containing("<groupId>org.testcontainers</groupId>")
+      .containing("<artifactId>mariadb</artifactId>")
       .and()
       .hasFile("src/main/resources/config/application.yml")
       .containing(
@@ -109,6 +164,15 @@ class JpaModuleFactoryTest {
             jpa:
               repositories:
                 bootstrap-mode: deferred
+          datasource:
+            driver-class-name: org.mariadb.jdbc.Driver
+            hikari:
+              auto-commit: false
+              poolName: Hikari
+            password: ''
+            type: com.zaxxer.hikari.HikariDataSource
+            url: jdbc:mariadb://localhost:3306/myapp
+            username: root
           jpa:
             hibernate:
               ddl-auto: none
@@ -130,6 +194,20 @@ class JpaModuleFactoryTest {
                   fail_on_pagination_over_collection_fetch: true
                   in_clause_parameter_padding: true
         """
+      )
+      .and()
+      .hasFile("src/test/resources/config/application-test.yml")
+      .containing(
+        """
+        spring:
+          datasource:
+            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
+            hikari:
+              maximum-pool-size: 2
+            password: ''
+            url: jdbc:tc:mariadb:0.0.0:///myapp
+            username: myapp
+        """
       );
   }
 
@@ -140,25 +218,36 @@ class JpaModuleFactoryTest {
       .projectBaseName("myapp")
       .build();
 
+    when(dockerImages.get("mysql")).thenReturn(new DockerImageVersion("mysql", "0.0.0"));
+
     JHipsterModule module = factory.buildMySQL(properties);
 
     assertThatModuleWithFiles(module, pomFile())
-      .hasFile("src/main/java/tech/jhipster/jhlitest/wire/database/infrastructure/secondary/DatabaseConfiguration.java")
-      .containing("package tech.jhipster.jhlitest.wire.database.infrastructure.secondary;")
+      .hasFile("documentation/mysql.md")
+      .containing("docker compose -f src/main/docker/mysql.yml up -d")
+      .and()
+      .hasFile("src/main/java/tech/jhipster/jhlitest/wire/mysql/infrastructure/secondary/DatabaseConfiguration.java")
+      .containing("package tech.jhipster.jhlitest.wire.mysql.infrastructure.secondary;")
       .and()
+      .hasPrefixedFiles("src/main/docker", "mysql.yml")
       .hasFile("pom.xml")
+      .containing("<groupId>org.springframework.boot</groupId>")
+      .containing("<artifactId>spring-boot-starter-data-jpa</artifactId>")
       .containing(
         """
-              <groupId>org.springframework.boot</groupId>
-              <artifactId>spring-boot-starter-data-jpa</artifactId>\
-        """
-      )
-      .containing(
-        """
-              <groupId>org.hibernate.orm</groupId>
-              <artifactId>hibernate-core</artifactId>\
+            <dependency>
+              <groupId>com.mysql</groupId>
+              <artifactId>mysql-connector-j</artifactId>
+              <scope>runtime</scope>
+            </dependency>
         """
       )
+      .containing("<groupId>com.zaxxer</groupId>")
+      .containing("<artifactId>HikariCP</artifactId>")
+      .containing("<groupId>org.hibernate.orm</groupId>")
+      .containing("<artifactId>hibernate-core</artifactId>")
+      .containing("<groupId>org.testcontainers</groupId>")
+      .containing("<artifactId>mysql</artifactId>")
       .and()
       .hasFile("src/main/resources/config/application.yml")
       .containing(
@@ -169,6 +258,15 @@ class JpaModuleFactoryTest {
             jpa:
               repositories:
                 bootstrap-mode: deferred
+          datasource:
+            driver-class-name: com.mysql.cj.jdbc.Driver
+            hikari:
+              auto-commit: false
+              poolName: Hikari
+            password: ''
+            type: com.zaxxer.hikari.HikariDataSource
+            url: jdbc:mysql://localhost:3306/myapp
+            username: root
           jpa:
             hibernate:
               ddl-auto: none
@@ -190,6 +288,21 @@ class JpaModuleFactoryTest {
                   fail_on_pagination_over_collection_fetch: true
                   in_clause_parameter_padding: true
         """
+      )
+      .and()
+      .hasFile("src/test/resources/config/application-test.yml")
+      .containing(
+        // language=yaml
+        """
+        spring:
+          datasource:
+            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
+            hikari:
+              maximum-pool-size: 2
+            password: ''
+            url: jdbc:tc:mysql:0.0.0:///myapp
+            username: myapp
+        """
       );
   }
 
@@ -200,25 +313,37 @@ class JpaModuleFactoryTest {
       .projectBaseName("myapp")
       .build();
 
+    when(dockerImages.get("mcr.microsoft.com/mssql/server")).thenReturn(new DockerImageVersion("mcr.microsoft.com/mssql/server", "0.0.0"));
+
     JHipsterModule module = factory.buildMsSQL(properties);
 
-    assertThatModuleWithFiles(module, pomFile())
-      .hasFile("src/main/java/tech/jhipster/jhlitest/wire/database/infrastructure/secondary/DatabaseConfiguration.java")
-      .containing("package tech.jhipster.jhlitest.wire.database.infrastructure.secondary;")
+    assertThatModuleWithFiles(module, pomFile(), integrationTestAnnotation())
+      .hasFile("src/main/java/tech/jhipster/jhlitest/wire/mssql/infrastructure/secondary/DatabaseConfiguration.java")
+      .containing("package tech.jhipster.jhlitest.wire.mssql.infrastructure.secondary;")
+      .and()
+      .hasFile("documentation/mssql.md")
+      .containing("docker compose -f src/main/docker/mssql.yml up -d")
+      .and()
+      .hasFile("src/test/java/tech/jhipster/jhlitest/MsSQLTestContainerExtension.java")
+      .and()
+      .hasFile("src/test/resources/container-license-acceptance.txt")
       .and()
       .hasFile("pom.xml")
       .containing(
         """
-              <groupId>org.springframework.boot</groupId>
-              <artifactId>spring-boot-starter-data-jpa</artifactId>\
-        """
-      )
-      .containing(
-        """
-              <groupId>org.hibernate.orm</groupId>
-              <artifactId>hibernate-core</artifactId>\
+            <dependency>
+              <groupId>com.microsoft.sqlserver</groupId>
+              <artifactId>mssql-jdbc</artifactId>
+              <scope>runtime</scope>
+            </dependency>
         """
       )
+      .containing("<groupId>com.zaxxer</groupId>")
+      .containing("<artifactId>HikariCP</artifactId>")
+      .containing("<groupId>org.hibernate.orm</groupId>")
+      .containing("<artifactId>hibernate-core</artifactId>")
+      .containing("<groupId>org.testcontainers</groupId>")
+      .containing("<artifactId>mssqlserver</artifactId>")
       .and()
       .hasFile("src/main/resources/config/application.yml")
       .containing(
@@ -229,6 +354,15 @@ class JpaModuleFactoryTest {
             jpa:
               repositories:
                 bootstrap-mode: deferred
+          datasource:
+            driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+            hikari:
+              auto-commit: false
+              poolName: Hikari
+            password: yourStrong(!)Password
+            type: com.zaxxer.hikari.HikariDataSource
+            url: jdbc:sqlserver://localhost:1433;database=myapp;trustServerCertificate=true
+            username: SA
           jpa:
             hibernate:
               ddl-auto: update
@@ -255,6 +389,25 @@ class JpaModuleFactoryTest {
                   fail_on_pagination_over_collection_fetch: true
                   in_clause_parameter_padding: true
         """
+      )
+      .and()
+      .hasFile("src/test/resources/config/application-test.yml")
+      .containing(
+        // language=yaml
+        """
+        spring:
+          datasource:
+            driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
+            hikari:
+              maximum-pool-size: 2
+            password: yourStrong(!)Password
+            url: jdbc:tc:sqlserver:///;database=myapp;trustServerCertificate=true?TC_TMPFS=/testtmpfs:rw
+            username: SA
+        """
       );
   }
+
+  private JHipsterModulesAssertions.ModuleFile integrationTestAnnotation() {
+    return file("src/test/resources/projects/files/IntegrationTest.java", "src/test/java/tech/jhipster/jhlitest/IntegrationTest.java");
+  }
 }
diff --git a/src/test/resources/projects/angular/app.component.spec.ts b/src/test/resources/projects/angular/app.component.spec.ts
index e5107cb21..87c6b7b58 100644
--- a/src/test/resources/projects/angular/app.component.spec.ts
+++ b/src/test/resources/projects/angular/app.component.spec.ts
@@ -21,7 +21,7 @@ describe('App Component', () => {
 
   describe('ngOnInit', () => {
     it('should have appName', () => {
-      expect(comp.appName()).toEqual('test');
+      expect(comp.appName()).toBe('test');
     });
   });
 });
diff --git a/src/test/webapp/unit/common/primary/timeout/Timeout.spec.ts b/src/test/webapp/unit/common/primary/timeout/Timeout.spec.ts
index 935e84ada..d2dc97e80 100644
--- a/src/test/webapp/unit/common/primary/timeout/Timeout.spec.ts
+++ b/src/test/webapp/unit/common/primary/timeout/Timeout.spec.ts
@@ -19,7 +19,7 @@ describe('Timeout', () => {
 
     vi.advanceTimersByTime(TIMEOUT_TIME);
 
-    expect(stub).toHaveBeenCalledTimes(1);
+    expect(stub).toHaveBeenCalledOnce();
   });
 
   it('should not launch timeout with less some time', () => {
@@ -28,7 +28,7 @@ describe('Timeout', () => {
 
     vi.advanceTimersByTime(LESS_TIME);
 
-    expect(stub).toHaveBeenCalledTimes(0);
+    expect(stub).not.toHaveBeenCalled();
   });
 
   it('should not launch timeout with unsubscribe', () => {
@@ -39,7 +39,7 @@ describe('Timeout', () => {
     timeout.unregister();
     vi.advanceTimersByTime(TIMEOUT_TIME);
 
-    expect(stub).toHaveBeenCalledTimes(0);
+    expect(stub).not.toHaveBeenCalled();
   });
 
   it('should not fail to unregister when not registered', () => {
@@ -58,7 +58,7 @@ describe('Timeout', () => {
     timeout.register(secondCall, TIMEOUT_TIME);
     vi.advanceTimersByTime(TIMEOUT_TIME);
 
-    expect(firstCall).toHaveBeenCalledTimes(0);
-    expect(secondCall).toHaveBeenCalledTimes(1);
+    expect(firstCall).not.toHaveBeenCalled();
+    expect(secondCall).toHaveBeenCalledOnce();
   });
 });
diff --git a/src/test/webapp/unit/common/primary/toast/Toast.spec.ts b/src/test/webapp/unit/common/primary/toast/Toast.spec.ts
index 4c24ba18a..3183f950f 100644
--- a/src/test/webapp/unit/common/primary/toast/Toast.spec.ts
+++ b/src/test/webapp/unit/common/primary/toast/Toast.spec.ts
@@ -97,8 +97,8 @@ describe('Toast', () => {
 
     wrapper.unmount();
 
-    expect(unsubscribeSuccess).toHaveBeenCalledTimes(1);
-    expect(unsubscribeError).toHaveBeenCalledTimes(1);
+    expect(unsubscribeSuccess).toHaveBeenCalledOnce();
+    expect(unsubscribeError).toHaveBeenCalledOnce();
   });
 
   describe('Timeout', () => {
diff --git a/src/test/webapp/unit/module/primary/landscape/LandscapeComponent.spec.ts b/src/test/webapp/unit/module/primary/landscape/LandscapeComponent.spec.ts
index 6af97b4a2..00de0c92d 100644
--- a/src/test/webapp/unit/module/primary/landscape/LandscapeComponent.spec.ts
+++ b/src/test/webapp/unit/module/primary/landscape/LandscapeComponent.spec.ts
@@ -168,7 +168,7 @@ describe('Landscape', () => {
         return mount(LandscapeVue);
       } catch (e) {
         if (e instanceof Error) {
-          expect(e.message).toEqual('repositoryWithLandscapeError');
+          expect(e.message).toBe('repositoryWithLandscapeError');
         }
         expect(console.error).toHaveBeenCalled();
       }
@@ -196,7 +196,7 @@ describe('Landscape', () => {
         return mount(LandscapeVue);
       } catch (e) {
         if (e instanceof Error) {
-          expect(e.message).toEqual('repositoryWithProjectFoldersErrorww');
+          expect(e.message).toBe('repositoryWithProjectFoldersErrorww');
         }
         expect(console.error).toHaveBeenCalled();
       }
@@ -209,7 +209,7 @@ describe('Landscape', () => {
       expect(wrapper.find(wrappedElement('landscape-loader')).exists()).toBe(false);
       expect(wrapper.find(wrappedElement('landscape')).exists()).toBe(true);
       expect(wrapper.find(wrappedElement('landscape-connectors')).findAll('path').length).toBe(17);
-      expect(applicationListener.addEventListener).toHaveBeenCalledTimes(1);
+      expect(applicationListener.addEventListener).toHaveBeenCalledOnce();
 
       const pathField = wrapper.find(wrappedElement('folder-path-field')).element as HTMLInputElement;
       expect(pathField.value).toBe('/tmp/jhlite/1234');
@@ -221,7 +221,7 @@ describe('Landscape', () => {
 
       wrapper.unmount();
 
-      expect(applicationListener.removeEventListener).toHaveBeenCalledTimes(1);
+      expect(applicationListener.removeEventListener).toHaveBeenCalledOnce();
     });
 
     it('should load folder path from local storage', async () => {
@@ -744,7 +744,7 @@ describe('Landscape', () => {
       const consoleErrors = vi.spyOn(console, 'error');
       await updatePath(wrapper);
 
-      expect(console.error).toHaveBeenCalledTimes(0);
+      expect(console.error).not.toHaveBeenCalled();
       consoleErrors.mockRestore();
     });
 
@@ -845,8 +845,7 @@ describe('Landscape', () => {
       const landscape = wrapper.find(wrappedElement('landscape-container'));
       await landscape.trigger('mousedown', mouseEvent);
 
-      expect(cursorUpdater.set).toHaveBeenCalledTimes(1);
-      expect(cursorUpdater.set).toBeCalledWith('grabbing');
+      expect(cursorUpdater.set).toHaveBeenCalledExactlyOnceWith('grabbing');
     });
 
     it('should prevent default clicking event when defined', async () => {
@@ -863,7 +862,7 @@ describe('Landscape', () => {
       const landscape = wrapper.find(wrappedElement('landscape-container'));
       await landscape.trigger('mousedown', mouseEvent);
 
-      expect(mouseEvent.preventDefault).toHaveBeenCalledTimes(1);
+      expect(mouseEvent.preventDefault).toHaveBeenCalledOnce();
     });
 
     it('should stop grabbing on mouseup', async () => {
@@ -875,7 +874,7 @@ describe('Landscape', () => {
       const landscape = wrapper.find(wrappedElement('landscape-container'));
       await landscape.trigger('mouseup');
 
-      expect(cursorUpdater.reset).toHaveBeenCalledTimes(1);
+      expect(cursorUpdater.reset).toHaveBeenCalledOnce();
     });
 
     it('should stop grabbing on mouseleave', async () => {
@@ -887,7 +886,7 @@ describe('Landscape', () => {
       const landscape = wrapper.find(wrappedElement('landscape-container'));
       await landscape.trigger('mouseleave');
 
-      expect(cursorUpdater.reset).toHaveBeenCalledTimes(1);
+      expect(cursorUpdater.reset).toHaveBeenCalledOnce();
     });
 
     it('should be scrolling', async () => {
@@ -909,8 +908,7 @@ describe('Landscape', () => {
       await landscape.trigger('mousedown', mouseEventStart);
       await landscape.trigger('mousemove', mouseEventGrabbed);
 
-      expect(landscapeScroller.scroll).toHaveBeenCalledTimes(1);
-      expect(landscapeScroller.scroll).toBeCalledWith(expect.anything(), 20, 20);
+      expect(landscapeScroller.scroll).toHaveBeenCalledExactlyOnceWith(expect.anything(), 20, 20);
     });
 
     it('should not scroll without starting grabbing', async () => {
@@ -926,7 +924,7 @@ describe('Landscape', () => {
       const landscape = wrapper.find(wrappedElement('landscape-container'));
       await landscape.trigger('mousemove', mouseEventGrabbed);
 
-      expect(landscapeScroller.scroll).toHaveBeenCalledTimes(0);
+      expect(landscapeScroller.scroll).not.toHaveBeenCalled();
     });
   });
 
@@ -1277,8 +1275,7 @@ describe('Landscape', () => {
 
       expect(mockModuleRect).toHaveBeenCalled();
       expect(mockContainerRect).toHaveBeenCalled();
-      expect(landscapeScroller.scrollIntoView).toHaveBeenCalledTimes(1);
-      expect(landscapeScroller.scrollIntoView).toHaveBeenCalledWith(prettierModule);
+      expect(landscapeScroller.scrollIntoView).toHaveBeenCalledExactlyOnceWith(prettierModule);
     });
 
     it('should not scroll if the highlighted module is already visible', async () => {
@@ -1321,8 +1318,7 @@ describe('Landscape', () => {
 
       await performSearch(searchInput, '');
 
-      expect(landscapeScroller.scrollSmooth).toHaveBeenCalledTimes(1);
-      expect(landscapeScroller.scrollSmooth).toHaveBeenCalledWith(landscapeContainer, 0, 0);
+      expect(landscapeScroller.scrollSmooth).toHaveBeenCalledExactlyOnceWith(landscapeContainer, 0, 0);
     });
 
     const setupSearchTest = async () => {
diff --git a/src/test/webapp/unit/module/primary/landscape/LandscapeConnector.spec.ts b/src/test/webapp/unit/module/primary/landscape/LandscapeConnector.spec.ts
index f2fd36d16..ecc7201f2 100644
--- a/src/test/webapp/unit/module/primary/landscape/LandscapeConnector.spec.ts
+++ b/src/test/webapp/unit/module/primary/landscape/LandscapeConnector.spec.ts
@@ -25,7 +25,7 @@ describe('LandscapeConnector', () => {
       ];
       const landscapeConnector: LandscapeConnector = new LandscapeConnector(positions, moduleSlug('moduleA'), moduleSlug('B'));
       //MoveTo 'startPoint', LineTo, CurveTo(3 points), LineTo, CurveTo(3 points), LineTo 'endPoint'
-      expect(landscapeConnector.path).toEqual('M 0 0 L 4 0 C 4 0 10 0 10 6 L 10 94 C 10 94 10 100 16 100 L 100 100');
+      expect(landscapeConnector.path).toBe('M 0 0 L 4 0 C 4 0 10 0 10 6 L 10 94 C 10 94 10 100 16 100 L 100 100');
     });
 
     it('should generate curved path for top-right dependant', () => {
@@ -49,7 +49,7 @@ describe('LandscapeConnector', () => {
       ];
       const landscapeConnector: LandscapeConnector = new LandscapeConnector(positions, moduleSlug('moduleA'), moduleSlug('B'));
       //MoveTo 'startPoint', LineTo, CurveTo(3 points), LineTo, CurveTo(3 points), LineTo 'endPoint'
-      expect(landscapeConnector.path).toEqual('M 100 100 L 104 100 C 104 100 110 100 110 94 L 110 6 C 110 6 110 0 116 0 L 200 0');
+      expect(landscapeConnector.path).toBe('M 100 100 L 104 100 C 104 100 110 100 110 94 L 110 6 C 110 6 110 0 116 0 L 200 0');
     });
   });
 });
diff --git a/src/test/webapp/unit/module/primary/landscape/LandscapeMiniMapComponent.spec.ts b/src/test/webapp/unit/module/primary/landscape/LandscapeMiniMapComponent.spec.ts
index c6e5afb75..7e07d780e 100644
--- a/src/test/webapp/unit/module/primary/landscape/LandscapeMiniMapComponent.spec.ts
+++ b/src/test/webapp/unit/module/primary/landscape/LandscapeMiniMapComponent.spec.ts
@@ -66,7 +66,7 @@ describe('MiniMap component', () => {
     await minimapViewer.trigger('mousemove');
     await wrapper.vm.$nextTick();
 
-    expect(landscapeContainer.scroll).toHaveBeenCalledTimes(0);
+    expect(landscapeContainer.scroll).not.toHaveBeenCalled();
   });
 
   it('should track the scroller position of the landscape container', async () => {
diff --git a/src/test/webapp/unit/module/primary/landscape/LandscapeScroller.spec.ts b/src/test/webapp/unit/module/primary/landscape/LandscapeScroller.spec.ts
index 394d786c4..4401ad661 100644
--- a/src/test/webapp/unit/module/primary/landscape/LandscapeScroller.spec.ts
+++ b/src/test/webapp/unit/module/primary/landscape/LandscapeScroller.spec.ts
@@ -18,8 +18,7 @@ describe('LandscapeScroller', () => {
 
     landscapeScroller.scroll(element, 10, 10);
 
-    expect(element.scroll).toHaveBeenCalledTimes(1);
-    expect(element.scroll).toBeCalledWith(10, 10);
+    expect(element.scroll).toHaveBeenCalledExactlyOnceWith(10, 10);
   });
 
   it('should scroll smooth', () => {
@@ -28,8 +27,7 @@ describe('LandscapeScroller', () => {
 
     landscapeScroller.scrollSmooth(element, 10, 10);
 
-    expect(element.scroll).toHaveBeenCalledTimes(1);
-    expect(element.scroll).toBeCalledWith({ left: 10, top: 10, behavior: 'smooth' });
+    expect(element.scroll).toHaveBeenCalledExactlyOnceWith({ left: 10, top: 10, behavior: 'smooth' });
   });
 
   it('should scroll into view', () => {
@@ -38,7 +36,6 @@ describe('LandscapeScroller', () => {
 
     landscapeScroller.scrollIntoView(element);
 
-    expect(element.scrollIntoView).toHaveBeenCalledTimes(1);
-    expect(element.scrollIntoView).toBeCalledWith({ behavior: 'smooth', block: 'center', inline: 'center' });
+    expect(element.scrollIntoView).toHaveBeenCalledExactlyOnceWith({ behavior: 'smooth', block: 'center', inline: 'center' });
   });
 });
diff --git a/src/test/webapp/unit/module/primary/modules-patch/ModulesPatchComponent.spec.ts b/src/test/webapp/unit/module/primary/modules-patch/ModulesPatchComponent.spec.ts
index a0649e180..bcb7176b5 100644
--- a/src/test/webapp/unit/module/primary/modules-patch/ModulesPatchComponent.spec.ts
+++ b/src/test/webapp/unit/module/primary/modules-patch/ModulesPatchComponent.spec.ts
@@ -81,7 +81,7 @@ describe('Modules', () => {
         return mount(ModulesVue);
       } catch (e) {
         if (e instanceof Error) {
-          expect(e.message).toEqual('repositoryWithModulesError');
+          expect(e.message).toBe('repositoryWithModulesError');
         }
         expect(console.error).toHaveBeenCalled();
       }
@@ -104,7 +104,7 @@ describe('Modules', () => {
         return mount(ModulesVue);
       } catch (e) {
         if (e instanceof Error) {
-          expect(e.message).toEqual('repositoryWithProjectFoldersError');
+          expect(e.message).toBe('repositoryWithProjectFoldersError');
         }
         expect(console.error).toHaveBeenCalled();
       }
diff --git a/src/test/webapp/unit/module/secondary/RestProjectFoldersRepository.spec.ts b/src/test/webapp/unit/module/secondary/RestProjectFoldersRepository.spec.ts
index cb7be083d..cef11b429 100644
--- a/src/test/webapp/unit/module/secondary/RestProjectFoldersRepository.spec.ts
+++ b/src/test/webapp/unit/module/secondary/RestProjectFoldersRepository.spec.ts
@@ -10,6 +10,6 @@ describe('Rest project folders repository', () => {
 
     const projectFolder = await repository.get();
 
-    expect(projectFolder).toEqual('/tmp/jhlite/1234');
+    expect(projectFolder).toBe('/tmp/jhlite/1234');
   });
 });
diff --git a/src/test/webapp/unit/shared/alert/infrastructure/primary/WindowApplicationListener.spec.ts b/src/test/webapp/unit/shared/alert/infrastructure/primary/WindowApplicationListener.spec.ts
index e41af011d..82dc0e329 100644
--- a/src/test/webapp/unit/shared/alert/infrastructure/primary/WindowApplicationListener.spec.ts
+++ b/src/test/webapp/unit/shared/alert/infrastructure/primary/WindowApplicationListener.spec.ts
@@ -9,7 +9,7 @@ describe('WindowApplicationListener', () => {
 
     windowApplicationListener.addEventListener('success', () => {});
 
-    expect(window.addEventListener).toHaveBeenCalledTimes(1);
+    expect(window.addEventListener).toHaveBeenCalledOnce();
   });
 
   it('should remove event listener on window', () => {
@@ -19,6 +19,6 @@ describe('WindowApplicationListener', () => {
 
     windowApplicationListener.removeEventListener('success', () => {});
 
-    expect(window.removeEventListener).toHaveBeenCalledTimes(1);
+    expect(window.removeEventListener).toHaveBeenCalledOnce();
   });
 });
diff --git a/src/test/webapp/unit/shared/alert/infrastructure/secondary/MittAlertBus.spec.ts b/src/test/webapp/unit/shared/alert/infrastructure/secondary/MittAlertBus.spec.ts
index b9179fa80..300509409 100644
--- a/src/test/webapp/unit/shared/alert/infrastructure/secondary/MittAlertBus.spec.ts
+++ b/src/test/webapp/unit/shared/alert/infrastructure/secondary/MittAlertBus.spec.ts
@@ -10,8 +10,7 @@ describe('MittAlertBus', () => {
 
     mittAlertBus.success('A message');
 
-    expect(emitterStub.emit).toHaveBeenCalledTimes(1);
-    expect(emitterStub.emit).toBeCalledWith(AlertType.SUCCESS, 'A message');
+    expect(emitterStub.emit).toHaveBeenCalledExactlyOnceWith(AlertType.SUCCESS, 'A message');
   });
 
   it('should emit error', () => {
@@ -20,7 +19,6 @@ describe('MittAlertBus', () => {
 
     mittAlertBus.error('A message');
 
-    expect(emitterStub.emit).toHaveBeenCalledTimes(1);
-    expect(emitterStub.emit).toBeCalledWith(AlertType.ERROR, 'A message');
+    expect(emitterStub.emit).toHaveBeenCalledExactlyOnceWith(AlertType.ERROR, 'A message');
   });
 });
diff --git a/src/test/webapp/unit/shared/alert/infrastructure/secondary/MittAlertListener.spec.ts b/src/test/webapp/unit/shared/alert/infrastructure/secondary/MittAlertListener.spec.ts
index 9b91059b9..d116466ee 100644
--- a/src/test/webapp/unit/shared/alert/infrastructure/secondary/MittAlertListener.spec.ts
+++ b/src/test/webapp/unit/shared/alert/infrastructure/secondary/MittAlertListener.spec.ts
@@ -12,8 +12,7 @@ describe('MittAlertListener', () => {
 
     emitter.emit(AlertType.SUCCESS, 'A message');
 
-    expect(spyAlerted).toHaveBeenCalledTimes(1);
-    expect(spyAlerted).toBeCalledWith('A message');
+    expect(spyAlerted).toHaveBeenCalledExactlyOnceWith('A message');
   });
 
   it('should unsubscribe success', () => {
@@ -39,8 +38,7 @@ describe('MittAlertListener', () => {
 
     emitter.emit(AlertType.ERROR, 'A message');
 
-    expect(spyAlerted).toHaveBeenCalledTimes(1);
-    expect(spyAlerted).toBeCalledWith('A message');
+    expect(spyAlerted).toHaveBeenCalledExactlyOnceWith('A message');
   });
 
   it('should unsubscribe error', () => {
diff --git a/src/test/webapp/unit/shared/logger/infrastructure/secondary/ConsoleLogger.spec.ts b/src/test/webapp/unit/shared/logger/infrastructure/secondary/ConsoleLogger.spec.ts
index 3811d769a..6cb5c9b3d 100644
--- a/src/test/webapp/unit/shared/logger/infrastructure/secondary/ConsoleLogger.spec.ts
+++ b/src/test/webapp/unit/shared/logger/infrastructure/secondary/ConsoleLogger.spec.ts
@@ -11,7 +11,6 @@ describe('ConsoleLogger', () => {
 
     consoleLogger.error('An error occurs', error);
 
-    expect(logger.error).toHaveBeenCalledTimes(1);
-    expect(logger.error).toBeCalledWith('An error occurs\n', error);
+    expect(logger.error).toHaveBeenCalledExactlyOnceWith('An error occurs\n', error);
   });
 });
diff --git a/tests-ci/generate.sh b/tests-ci/generate.sh
index 4fb7847cf..7b96735df 100755
--- a/tests-ci/generate.sh
+++ b/tests-ci/generate.sh
@@ -167,7 +167,6 @@ elif [[ $application == fullapp* ]]; then
   apply_modules "spring-boot-cucumber-jpa-reset"
 
   apply_modules \
-    "datasource-postgresql" \
     "jpa-postgresql" \
     "liquibase" \
     "liquibase-linter" \
@@ -221,7 +220,6 @@ elif [[ $application == 'mysqlapp' ]]; then
   sonar_back
 
   apply_modules \
-    "datasource-mysql" \
     "jpa-mysql" \
     "liquibase"
 
@@ -244,10 +242,7 @@ elif [[ $application == 'mariadbapp' ]]; then
   sonar_back
 
   apply_modules "springdoc-mvc-openapi"
-  apply_modules \
-    "datasource-mariadb" \
-    "jpa-mariadb" \
-    "liquibase"
+  apply_modules "jpa-mariadb" "liquibase"
   apply_modules "ehcache-xml-config"
 
 elif [[ $application == 'mssqlapp' ]]; then
@@ -256,20 +251,14 @@ elif [[ $application == 'mssqlapp' ]]; then
   sonar_back
 
   apply_modules "springdoc-mvc-openapi"
-  apply_modules \
-    "datasource-mssql" \
-    "jpa-mssql"
+  apply_modules "jpa-mssql"
 
 elif [[ $application == 'flywayapp' ]]; then
   init_server
   spring_boot_mvc
   sonar_back
 
-  apply_modules \
-    "datasource-postgresql" \
-    "jpa-postgresql" \
-    "flyway" \
-    "flyway-postgresql"
+  apply_modules "jpa-postgresql" "flyway" "flyway-postgresql"
 
   cucumber_with_jwt
   apply_modules "spring-boot-cucumber-jpa-reset"
@@ -287,7 +276,6 @@ elif [[ $application == 'undertowapp' ]]; then
   sonar_back
 
   apply_modules \
-    "datasource-mysql" \
     "jpa-mysql" \
     "flyway" \
     "flyway-mysql"