diff --git a/spring-services-all/src/test/java/com/example/aggregate/AggregateTestConfig.java b/spring-services-all/src/test/java/com/example/aggregate/AggregateTestConfig.java index a5c8358..9b2c070 100644 --- a/spring-services-all/src/test/java/com/example/aggregate/AggregateTestConfig.java +++ b/spring-services-all/src/test/java/com/example/aggregate/AggregateTestConfig.java @@ -17,7 +17,10 @@ public class AggregateTestConfig { @Bean @ServiceConnection public PostgreSQLContainer> postgresContainer() { - return new PostgreSQLContainer<>("postgres:16-alpine"); + return new PostgreSQLContainer<>("postgres:16-alpine") + // Pre-create the dedicated schema so Hibernate's create-drop startup DROP phase does not + // log a CommandAcceptanceException for the not-yet-existing oe_spring_services schema. + .withInitScript("db/create-schema.sql"); } @Bean diff --git a/spring-services-all/src/test/resources/db/create-schema.sql b/spring-services-all/src/test/resources/db/create-schema.sql new file mode 100644 index 0000000..df56459 --- /dev/null +++ b/spring-services-all/src/test/resources/db/create-schema.sql @@ -0,0 +1,5 @@ +-- Pre-create the library's dedicated schema so Hibernate's create-drop startup DROP phase +-- (which emits an unguarded "drop schema oe_spring_services") has an existing schema to drop +-- on the first run against a fresh Testcontainer. Without this, Hibernate logs a harmless but +-- noisy CommandAcceptanceException before recreating the schema. +CREATE SCHEMA IF NOT EXISTS oe_spring_services; diff --git a/spring-services-core/src/test/java/com/openelements/spring/base/security/user/UserServiceActiveGateIntegrationTest.java b/spring-services-core/src/test/java/com/openelements/spring/base/security/user/UserServiceActiveGateIntegrationTest.java index 8612764..bf0f32a 100644 --- a/spring-services-core/src/test/java/com/openelements/spring/base/security/user/UserServiceActiveGateIntegrationTest.java +++ b/spring-services-core/src/test/java/com/openelements/spring/base/security/user/UserServiceActiveGateIntegrationTest.java @@ -19,7 +19,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.access.AccessDeniedException; @@ -49,7 +49,7 @@ * transactional configuration — entities are flushed and reloaded across transactions so the * assertions reflect what is durably in the database, not just the session cache. * - *
Mock-Audit. A single {@code @MockBean AuthService} is the only mock. The real + *
Mock-Audit. A single {@code @MockitoBean AuthService} is the only mock. The real * {@code AuthService} would require a Spring Security {@code SecurityContextHolder} populated by * the filter chain, which these tests deliberately bypass to drive {@code getCurrentUserEntity()} * directly. The {@code UserService}, {@link UserRepository}, and {@code UserProvisioner} under @@ -68,7 +68,7 @@ class UserServiceActiveGateIntegrationTest { @Autowired private JdbcTemplate jdbcTemplate; - @MockBean private AuthService authService; + @MockitoBean private AuthService authService; /** * Deletes dependent {@code audit_log} rows before the {@code users} rows they reference, then diff --git a/spring-services-core/src/test/java/com/openelements/spring/base/security/user/UserServiceConcurrencyTest.java b/spring-services-core/src/test/java/com/openelements/spring/base/security/user/UserServiceConcurrencyTest.java index 3d35b76..0a97cd2 100644 --- a/spring-services-core/src/test/java/com/openelements/spring/base/security/user/UserServiceConcurrencyTest.java +++ b/spring-services-core/src/test/java/com/openelements/spring/base/security/user/UserServiceConcurrencyTest.java @@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ActiveProfiles; @@ -69,7 +69,7 @@ * in-memory database faithfully reproduces. * *
Mock surface and justification. {@link - * com.openelements.spring.base.security.AuthService} is the single {@code @MockBean} — it would + * com.openelements.spring.base.security.AuthService} is the single {@code @MockitoBean} — it would * otherwise require a Spring Security {@code SecurityContextHolder} populated by the filter * chain, which the tests deliberately bypass to drive {@code getCurrentUserEntity()} directly * on background threads. Per-thread {@code UserInformation} dispatch is implemented with a @@ -100,7 +100,7 @@ class UserServiceConcurrencyTest { @Autowired private JdbcTemplate jdbcTemplate; - @MockBean private AuthService authService; + @MockitoBean private AuthService authService; /** * Deletes dependent {@code audit_log} rows before the {@code users} rows they reference, then diff --git a/spring-services-core/src/test/java/com/openelements/spring/base/services/apikey/ApiKeyDataServiceIntegrationTest.java b/spring-services-core/src/test/java/com/openelements/spring/base/services/apikey/ApiKeyDataServiceIntegrationTest.java index 5519066..f8bd122 100644 --- a/spring-services-core/src/test/java/com/openelements/spring/base/services/apikey/ApiKeyDataServiceIntegrationTest.java +++ b/spring-services-core/src/test/java/com/openelements/spring/base/services/apikey/ApiKeyDataServiceIntegrationTest.java @@ -18,7 +18,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -46,7 +46,7 @@ * service, and the {@link ApiKeyRepository} is the real Spring Data repository writing to the * containerised database. * - *
Mock-Audit. Two {@code @MockBean}s: + *
Mock-Audit. Two {@code @MockitoBean}s: * *
Mock-Audit. {@code AuthService} is the single {@code @MockBean} — real + *
Mock-Audit. {@code AuthService} is the single {@code @MockitoBean} — real * {@code AuthService} reads from {@link * org.springframework.security.core.context.SecurityContextHolder} populated by the filter * chain, which the tests deliberately bypass to drive listener decisions directly. Every other @@ -94,7 +94,7 @@ class AuditLogIntegrationTest { @Autowired private JdbcTemplate jdbcTemplate; - @MockBean private AuthService authService; + @MockitoBean private AuthService authService; private UserEntity alice; private UserEntity bob; diff --git a/spring-services-core/src/test/java/com/openelements/spring/base/services/tag/TagDataServiceIntegrationTest.java b/spring-services-core/src/test/java/com/openelements/spring/base/services/tag/TagDataServiceIntegrationTest.java index e8d7238..13aef77 100644 --- a/spring-services-core/src/test/java/com/openelements/spring/base/services/tag/TagDataServiceIntegrationTest.java +++ b/spring-services-core/src/test/java/com/openelements/spring/base/services/tag/TagDataServiceIntegrationTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -41,7 +41,7 @@ * are real beans; the per-test {@code @BeforeEach} truncates the {@code tag} table to keep * scenarios independent. * - *
Mock-Audit. One {@code @MockBean} of {@link AuthService}. The service inherits from + *
Mock-Audit. One {@code @MockitoBean} of {@link AuthService}. The service inherits from * {@code AbstractDbBackedDataService}, whose audit hooks consult {@code AuthService} for the * acting principal — outside a real HTTP request there is no JWT to resolve, so the bean is * mocked to default-stub behaviour. No other collaborator is mocked: every assertion is made @@ -58,7 +58,7 @@ class TagDataServiceIntegrationTest { @Autowired private TagRepository tagRepository; - @MockBean private AuthService authService; + @MockitoBean private AuthService authService; @BeforeEach void setUp() { diff --git a/spring-services-core/src/test/java/com/openelements/spring/base/services/webhook/data/WebhookDataServiceIntegrationTest.java b/spring-services-core/src/test/java/com/openelements/spring/base/services/webhook/data/WebhookDataServiceIntegrationTest.java index 58cfef8..409f2bc 100644 --- a/spring-services-core/src/test/java/com/openelements/spring/base/services/webhook/data/WebhookDataServiceIntegrationTest.java +++ b/spring-services-core/src/test/java/com/openelements/spring/base/services/webhook/data/WebhookDataServiceIntegrationTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.Import; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -42,7 +42,7 @@ * WebhookRepository} are real beans; the per-test {@code @BeforeEach} truncates the {@code * webhook} table to keep scenarios independent. * - *
Mock-Audit. One {@code @MockBean} of {@link AuthService}. The service inherits from + *
Mock-Audit. One {@code @MockitoBean} of {@link AuthService}. The service inherits from * {@code AbstractDbBackedDataService}, whose audit hooks consult {@code AuthService} for the * acting principal — outside a real HTTP request there is no JWT to resolve, so the bean is * mocked to default-stub behaviour. No other collaborator is mocked: every assertion is made @@ -59,7 +59,7 @@ class WebhookDataServiceIntegrationTest { @Autowired private WebhookRepository webhookRepository; - @MockBean private AuthService authService; + @MockitoBean private AuthService authService; @BeforeEach void setUp() { diff --git a/spring-services-core/src/test/java/com/openelements/spring/base/testcontainers/PostgresTestConfiguration.java b/spring-services-core/src/test/java/com/openelements/spring/base/testcontainers/PostgresTestConfiguration.java index 7648c7a..808b757 100644 --- a/spring-services-core/src/test/java/com/openelements/spring/base/testcontainers/PostgresTestConfiguration.java +++ b/spring-services-core/src/test/java/com/openelements/spring/base/testcontainers/PostgresTestConfiguration.java @@ -17,7 +17,10 @@ public class PostgresTestConfiguration { @Bean @ServiceConnection public PostgreSQLContainer> postgresContainer() { - return new PostgreSQLContainer<>("postgres:16-alpine"); + return new PostgreSQLContainer<>("postgres:16-alpine") + // Pre-create the dedicated schema so Hibernate's create-drop startup DROP phase does not + // log a CommandAcceptanceException for the not-yet-existing oe_spring_services schema. + .withInitScript("db/create-schema.sql"); } @Bean diff --git a/spring-services-core/src/test/resources/application-testcontainers.properties b/spring-services-core/src/test/resources/application-testcontainers.properties index 2d2754e..f94f651 100644 --- a/spring-services-core/src/test/resources/application-testcontainers.properties +++ b/spring-services-core/src/test/resources/application-testcontainers.properties @@ -2,9 +2,12 @@ spring.jpa.hibernate.ddl-auto=create-drop # Required so create-drop provisions the dedicated oe_spring_services schema before creating the # schema-qualified tables (Hibernate does not create a namespace/schema for an entity otherwise). spring.jpa.properties.hibernate.hbm2ddl.create_namespaces=true -spring.jpa.show-sql=true -spring.jpa.properties.hibernate.format_sql=true +# generate_statistics stays enabled: CommentServiceIntegrationTest asserts batch-fetch behaviour +# via the Hibernate Statistics API (SessionFactory.getStatistics()). It is the collection of the +# stats we need, not their logging — so we silence the per-session "Session Metrics {...}" dumps +# that StatisticalLoggingSessionEventListener would otherwise emit at INFO for every session. spring.jpa.properties.hibernate.generate_statistics=true +logging.level.org.hibernate.engine.internal.StatisticalLoggingSessionEventListener=WARN # Allow PostgresTestConfiguration test beans (e.g. webhookRestClient) to override the # production beans from the library's @Configuration classes. diff --git a/spring-services-core/src/test/resources/db/create-schema.sql b/spring-services-core/src/test/resources/db/create-schema.sql new file mode 100644 index 0000000..df56459 --- /dev/null +++ b/spring-services-core/src/test/resources/db/create-schema.sql @@ -0,0 +1,5 @@ +-- Pre-create the library's dedicated schema so Hibernate's create-drop startup DROP phase +-- (which emits an unguarded "drop schema oe_spring_services") has an existing schema to drop +-- on the first run against a fresh Testcontainer. Without this, Hibernate logs a harmless but +-- noisy CommandAcceptanceException before recreating the schema. +CREATE SCHEMA IF NOT EXISTS oe_spring_services;