Configuring Java Spring boot for testing w/ H2 and running w/ MySQL

I am setting up a microservice using Java Spring Boot. The application runs in a Docker container and connects to a MySQL database on the local machine. For testing purposes, I want to avoid the overhead of MySQL and use an H2 in-memory database for unit tests instead.

The following files are part of the configuration: build.gradle, application.properties, application-test.properties, and Dockerfile

Despite following some online guides, I am encountering build errors:

java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@44976b08 testClass = com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplicationTests, locations = [], classes = [com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.autoconfigure.OnFailureConditionReportContextCustomizerFactory$OnFailureConditionReportContextCustomizer@5023bb8b, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@604f2bd2, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@30b19518, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@62e20a76, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@28e8dde3, org.springframework.boot.test.web.reactor.netty.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory$DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer@59252cb6, org.springframework.test.context.support.DynamicPropertiesContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestAnnotation@cc9a5aaa], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:180)
<snip>  
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802)
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
<snip>  
    at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
    at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
    at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
    ... 19 more
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:276)
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
<snip>  
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1849)
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1798)
    ... 39 more
Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:154)
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveStrategy(StrategySelectorImpl.java:236)
<snip>  
    at app//org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
    ... 54 more
Caused by: org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [org.hibernate.dialect.MySQL5Dialect]
    at app//org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:126)
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:150)
    ... 64 more
Caused by: java.lang.ClassNotFoundException: Could not load requested class : org.hibernate.dialect.MySQL5Dialect
    at org.hibernate.boot.registry.classloading.internal.AggregatedClassLoader.findClass(AggregatedClassLoader.java:216)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:467)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:123)
    ... 65 more

The repository with my current setup can be found here:
GitHub Repository: [apptraqer (ehc/ArchitectureOverview branch)]1

What is the best way to configure Spring Boot to use H2 for unit tests, while keeping MySQL as the runtime configuration? I’d appreciate guidance on how to adjust the mentioned files and resolve these errors.

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.4.0'
    id 'io.spring.dependency-management' version '1.1.6'
    id 'application'
}

application {
    mainClass = 'com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication'
}

bootJar {
    mainClass = 'com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication'
}

group = 'com.apptraqer'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    // Spring Boot Starters
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // OAuth2 and Security Enhancements
    implementation 'org.springframework.security:spring-security-oauth2-jose'

    // JSON Web Token (JJWT)
    implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-orgjson:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

    // Database Connector
    runtimeOnly  'mysql:mysql-connector-java:8.0.26'

    // Testing Dependencies
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testImplementation 'com.h2database:h2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    implementation 'javax.persistence:javax.persistence-api:2.2'
    implementation 'javax.xml.bind:jaxb-api:2.3.1'
}

tasks.named('test') {
    useJUnitPlatform()
}

tasks.withType(JavaCompile) {
    options.compilerArgs << "-Xlint:deprecation"
}

It is my impression I need to have two application.properties, one for the Docker container and one for the test:

application.properties

# application.properties (Common Settings for All Environments)

# Application Name and Port (could be overridden per environment if needed)
spring.application.name=apptraqer-auth-service
server.port=8081

# Database Configuration (default to MySQL for non-test environments)
spring.datasource.url=jdbc:mysql://apptraqer-mysql:3306/apptraqerdata
spring.datasource.username=${SPRING_DATASOURCE_USERNAME}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Hibernate/JPA Settings (should be the same across all environments)
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

application-test.properties

# application-test.properties (Test Environment Overrides)

# Override Database Configuration for Test with H2 (or whatever you use in tests)
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

#H2 settings
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

Dockerfile

FROM openjdk:17-jdk-slim as build

WORKDIR /app

COPY build.gradle settings.gradle ./

COPY gradlew ./
COPY gradle/wrapper/ ./gradle/wrapper/

ENV SPRING_PROFILES_ACTIVE=test

RUN ./gradlew build --no-daemon

COPY src ./src

RUN ./gradlew build

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY --from=build /app/build/libs/apptraqer-auth-service.jar apptraqer-auth-service.jar

EXPOSE 8081

CMD ["java", "-jar", "apptraqer-auth-service.jar"]

1

Here are the changes I had to do for making the application to build properly.

For simple and straight forward configuration of H2 for the purpose of running unit tests we can use the @AutoConfigureTestDatabase as explained at the end of the Auto-configured Data JPA Tests section in the spring boot documentation. This will configure a test datasource based on what we add in the classpath which is H2 in our case.
Here is a sample of how we can add the annotation in the code

@SpringBootTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
class UserTest{}

Do note that the above is needed for only replacing the Datasource bean we are creating in the application. However say by moving the datasource properties to a separate config file each for tests and application like having the MySQL datasource configs in a file called application-docker.yaml and not providing any datasource configs in any other yaml file. This way when our datasource is autoconfigured it does not always know the MySQL configs (unless profile docker is active). In this setup spring boot can detect H2 on the classpath and will configure H2 automatically for us. And when deploying we can run the application in docker with the profile docker active to instruct spring boot to connect to MySQL. Similarly when running unit tests we do not activate the profile docker and spring boot will configure H2 then.

Some other corrections I was able to find are.

  • Spring boot 3.4 no longer depends on javax JPA APIs
    this dependency must be removed implementation 'javax.persistence:javax.persistence-api:2.2' and the JPA imports must be from jakarta package which is pulled transitively by spring boot starter jpa
  • Since we are configuring MySQL dialect in application.properties and H2 dialect in application-test.properties for spring boot to use application-test.properties config we need to activate the test profile when running unit tests. One simple way I know is by adding the @ActiveProfiles annotation above the test class like this
    @ActiveProfiles(profiles = {"test"})

Hope this helps.

In Gradle you can put

tasks.named('test') {
    useJUnitPlatform()
    systemProperty("spring.profiles.active", "test")
}

to set your Spring Profile to test for this task.

New contributor

TobiMoss is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Configuring Java Spring boot for testing w/ H2 and running w/ MySQL

I am setting up a microservice using Java Spring Boot. The application runs in a Docker container and connects to a MySQL database on the local machine. For testing purposes, I want to avoid the overhead of MySQL and use an H2 in-memory database for unit tests instead.

The following files are part of the configuration: build.gradle, application.properties, application-test.properties, and Dockerfile

Despite following some online guides, I am encountering build errors:

java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@44976b08 testClass = com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplicationTests, locations = [], classes = [com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.autoconfigure.OnFailureConditionReportContextCustomizerFactory$OnFailureConditionReportContextCustomizer@5023bb8b, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@604f2bd2, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@30b19518, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@62e20a76, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@28e8dde3, org.springframework.boot.test.web.reactor.netty.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory$DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer@59252cb6, org.springframework.test.context.support.DynamicPropertiesContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestAnnotation@cc9a5aaa], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:180)
<snip>  
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802)
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
<snip>  
    at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
    at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
    at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
    ... 19 more
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:276)
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
<snip>  
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1849)
    at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1798)
    ... 39 more
Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.hibernate.dialect.MySQL5Dialect] as strategy [org.hibernate.dialect.Dialect]
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:154)
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveStrategy(StrategySelectorImpl.java:236)
<snip>  
    at app//org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
    at app//org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
    ... 54 more
Caused by: org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [org.hibernate.dialect.MySQL5Dialect]
    at app//org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:126)
    at app//org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:150)
    ... 64 more
Caused by: java.lang.ClassNotFoundException: Could not load requested class : org.hibernate.dialect.MySQL5Dialect
    at org.hibernate.boot.registry.classloading.internal.AggregatedClassLoader.findClass(AggregatedClassLoader.java:216)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:467)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:123)
    ... 65 more

The repository with my current setup can be found here:
GitHub Repository: [apptraqer (ehc/ArchitectureOverview branch)]1

What is the best way to configure Spring Boot to use H2 for unit tests, while keeping MySQL as the runtime configuration? I’d appreciate guidance on how to adjust the mentioned files and resolve these errors.

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.4.0'
    id 'io.spring.dependency-management' version '1.1.6'
    id 'application'
}

application {
    mainClass = 'com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication'
}

bootJar {
    mainClass = 'com.apptraqer.apptraqerauthservice.ApptraqerAuthServiceApplication'
}

group = 'com.apptraqer'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    // Spring Boot Starters
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // OAuth2 and Security Enhancements
    implementation 'org.springframework.security:spring-security-oauth2-jose'

    // JSON Web Token (JJWT)
    implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-orgjson:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

    // Database Connector
    runtimeOnly  'mysql:mysql-connector-java:8.0.26'

    // Testing Dependencies
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testImplementation 'com.h2database:h2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    implementation 'javax.persistence:javax.persistence-api:2.2'
    implementation 'javax.xml.bind:jaxb-api:2.3.1'
}

tasks.named('test') {
    useJUnitPlatform()
}

tasks.withType(JavaCompile) {
    options.compilerArgs << "-Xlint:deprecation"
}

It is my impression I need to have two application.properties, one for the Docker container and one for the test:

application.properties

# application.properties (Common Settings for All Environments)

# Application Name and Port (could be overridden per environment if needed)
spring.application.name=apptraqer-auth-service
server.port=8081

# Database Configuration (default to MySQL for non-test environments)
spring.datasource.url=jdbc:mysql://apptraqer-mysql:3306/apptraqerdata
spring.datasource.username=${SPRING_DATASOURCE_USERNAME}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Hibernate/JPA Settings (should be the same across all environments)
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

application-test.properties

# application-test.properties (Test Environment Overrides)

# Override Database Configuration for Test with H2 (or whatever you use in tests)
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

#H2 settings
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

Dockerfile

FROM openjdk:17-jdk-slim as build

WORKDIR /app

COPY build.gradle settings.gradle ./

COPY gradlew ./
COPY gradle/wrapper/ ./gradle/wrapper/

ENV SPRING_PROFILES_ACTIVE=test

RUN ./gradlew build --no-daemon

COPY src ./src

RUN ./gradlew build

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY --from=build /app/build/libs/apptraqer-auth-service.jar apptraqer-auth-service.jar

EXPOSE 8081

CMD ["java", "-jar", "apptraqer-auth-service.jar"]

1

Here are the changes I had to do for making the application to build properly.

For simple and straight forward configuration of H2 for the purpose of running unit tests we can use the @AutoConfigureTestDatabase as explained at the end of the Auto-configured Data JPA Tests section in the spring boot documentation. This will configure a test datasource based on what we add in the classpath which is H2 in our case.
Here is a sample of how we can add the annotation in the code

@SpringBootTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
class UserTest{}

Do note that the above is needed for only replacing the Datasource bean we are creating in the application. However say by moving the datasource properties to a separate config file each for tests and application like having the MySQL datasource configs in a file called application-docker.yaml and not providing any datasource configs in any other yaml file. This way when our datasource is autoconfigured it does not always know the MySQL configs (unless profile docker is active). In this setup spring boot can detect H2 on the classpath and will configure H2 automatically for us. And when deploying we can run the application in docker with the profile docker active to instruct spring boot to connect to MySQL. Similarly when running unit tests we do not activate the profile docker and spring boot will configure H2 then.

Some other corrections I was able to find are.

  • Spring boot 3.4 no longer depends on javax JPA APIs
    this dependency must be removed implementation 'javax.persistence:javax.persistence-api:2.2' and the JPA imports must be from jakarta package which is pulled transitively by spring boot starter jpa
  • Since we are configuring MySQL dialect in application.properties and H2 dialect in application-test.properties for spring boot to use application-test.properties config we need to activate the test profile when running unit tests. One simple way I know is by adding the @ActiveProfiles annotation above the test class like this
    @ActiveProfiles(profiles = {"test"})

Hope this helps.

In Gradle you can put

tasks.named('test') {
    useJUnitPlatform()
    systemProperty("spring.profiles.active", "test")
}

to set your Spring Profile to test for this task.

New contributor

TobiMoss is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật