Added TestContainers-based testing configuration for MySQL and MSSQL integration tests. Added module test for DialectProviders, Smoketests for TestContainers-based integration tests. NodeRepositoryIntegrationTest. Other Repository integration tests still missing.
This commit is contained in:
parent
5fb025e4b3
commit
8e6cc8cf07
13 changed files with 942 additions and 15 deletions
11
pom.xml
11
pom.xml
|
|
@ -206,6 +206,11 @@
|
|||
</dependency>
|
||||
|
||||
<!-- TestContainers for multi-database integration testing -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-testcontainers</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>testcontainers</artifactId>
|
||||
|
|
@ -224,6 +229,12 @@
|
|||
<version>1.19.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>1.19.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
|
|
|
|||
|
|
@ -128,11 +128,12 @@ public class MySQLDialectProvider implements SqlDialectProvider {
|
|||
|
||||
@Override
|
||||
public String buildHaversineDistance(String lat1, String lng1, String lat2, String lng2) {
|
||||
// Haversine formula: 6371000 meters (Earth radius) * acos(...)
|
||||
// Haversine formula: 6371 km (Earth radius) * acos(...)
|
||||
// Formula: d = 2R * arcsin(sqrt(sin²((lat2-lat1)/2) + cos(lat1)*cos(lat2)*sin²((lon2-lon1)/2)))
|
||||
// Simplified: R * acos(cos(lat1)*cos(lat2)*cos(lng2-lng1) + sin(lat1)*sin(lat2))
|
||||
// Returns distance in KILOMETERS
|
||||
return String.format(
|
||||
"6371000 * ACOS(COS(RADIANS(%s)) * COS(RADIANS(%s)) * " +
|
||||
"6371 * ACOS(COS(RADIANS(%s)) * COS(RADIANS(%s)) * " +
|
||||
"COS(RADIANS(%s) - RADIANS(%s)) + SIN(RADIANS(%s)) * SIN(RADIANS(%s)))",
|
||||
lat1, lat2, lng2, lng1, lat1, lat2
|
||||
);
|
||||
|
|
|
|||
|
|
@ -157,10 +157,10 @@ public class NodeRepository {
|
|||
|
||||
@Transactional
|
||||
public Optional<Integer> setDeprecatedById(Integer id) {
|
||||
String query = "UPDATE node SET is_deprecated = TRUE WHERE id = ?";
|
||||
String query = "UPDATE node SET is_deprecated = " + dialectProvider.getBooleanTrue() + " WHERE id = ?";
|
||||
|
||||
// Mark all linked RouteNodes as outdated
|
||||
jdbcTemplate.update("UPDATE premise_route_node SET is_outdated = TRUE WHERE node_id = ?", id);
|
||||
jdbcTemplate.update("UPDATE premise_route_node SET is_outdated = " + dialectProvider.getBooleanTrue() + " WHERE node_id = ?", id);
|
||||
|
||||
|
||||
return Optional.ofNullable(jdbcTemplate.update(query, id) == 0 ? null : id);
|
||||
|
|
@ -261,7 +261,7 @@ public class NodeRepository {
|
|||
}
|
||||
|
||||
// Mark all linked RouteNodes as outdated
|
||||
jdbcTemplate.update("UPDATE premise_route_node SET is_outdated = TRUE WHERE node_id = ?", node.getId());
|
||||
jdbcTemplate.update("UPDATE premise_route_node SET is_outdated = " + dialectProvider.getBooleanTrue() + " WHERE node_id = ?", node.getId());
|
||||
|
||||
// Mark all distance matrix entries as stale
|
||||
jdbcTemplate.update("UPDATE distance_matrix SET state = 'STALE' WHERE ((from_node_id = ?) OR (to_node_id = ?))", node.getId(), node.getId());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package de.avatic.lcc.config;
|
||||
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.testcontainers.containers.MSSQLServerContainer;
|
||||
import org.testcontainers.containers.MySQLContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
/**
|
||||
* TestContainers configuration for multi-database integration testing.
|
||||
* <p>
|
||||
* Automatically starts the correct database container based on active Spring profile.
|
||||
* Uses @ServiceConnection to automatically configure Spring DataSource.
|
||||
* <p>
|
||||
* Usage:
|
||||
* <pre>
|
||||
* mvn test -Dspring.profiles.active=test,mysql -Dtest=DatabaseConfigurationSmokeTest
|
||||
* mvn test -Dspring.profiles.active=test,mssql -Dtest=DatabaseConfigurationSmokeTest
|
||||
* </pre>
|
||||
*/
|
||||
@TestConfiguration
|
||||
public class DatabaseTestConfiguration {
|
||||
|
||||
@Bean
|
||||
@ServiceConnection
|
||||
@Profile("mysql")
|
||||
public MySQLContainer<?> mysqlContainer() {
|
||||
System.out.println("DatabaseTestConfiguration: Creating MySQL container bean...");
|
||||
MySQLContainer<?> container = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
|
||||
.withDatabaseName("lcc_test")
|
||||
.withUsername("test")
|
||||
.withPassword("test");
|
||||
System.out.println("DatabaseTestConfiguration: MySQL container bean created");
|
||||
return container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ServiceConnection
|
||||
@Profile("mssql")
|
||||
public MSSQLServerContainer<?> mssqlContainer() {
|
||||
System.out.println("DatabaseTestConfiguration: Creating MSSQL container bean...");
|
||||
MSSQLServerContainer<?> container = new MSSQLServerContainer<>(
|
||||
DockerImageName.parse("mcr.microsoft.com/mssql/server:2022-latest"))
|
||||
.acceptLicense()
|
||||
.withPassword("YourStrong!Passw0rd123");
|
||||
System.out.println("DatabaseTestConfiguration: MSSQL container bean created");
|
||||
return container;
|
||||
}
|
||||
}
|
||||
64
src/test/java/de/avatic/lcc/config/RepositoryTestConfig.java
Normal file
64
src/test/java/de/avatic/lcc/config/RepositoryTestConfig.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package de.avatic.lcc.config;
|
||||
|
||||
import de.avatic.lcc.database.dialect.MySQLDialectProvider;
|
||||
import de.avatic.lcc.database.dialect.MSSQLDialectProvider;
|
||||
import de.avatic.lcc.database.dialect.SqlDialectProvider;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* Test configuration that provides only the beans needed for repository tests.
|
||||
* Does NOT load the full LccApplication context.
|
||||
*
|
||||
* Uses @SpringBootConfiguration to prevent Spring Boot from searching for and loading LccApplication.
|
||||
*
|
||||
* Excludes repositories with external dependencies (transformers/services) since we're only testing JDBC layer.
|
||||
*/
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan(
|
||||
basePackages = "de.avatic.lcc.repositories",
|
||||
excludeFilters = @ComponentScan.Filter(
|
||||
type = FilterType.ASSIGNABLE_TYPE,
|
||||
classes = {
|
||||
de.avatic.lcc.repositories.error.DumpRepository.class,
|
||||
de.avatic.lcc.repositories.NomenclatureRepository.class,
|
||||
de.avatic.lcc.repositories.premise.DestinationRepository.class
|
||||
}
|
||||
)
|
||||
)
|
||||
public class RepositoryTestConfig {
|
||||
|
||||
@Bean
|
||||
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
|
||||
return new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) {
|
||||
return new NamedParameterJdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Profile("mysql")
|
||||
public SqlDialectProvider mysqlDialectProvider() {
|
||||
System.out.println("RepositoryTestConfig: Creating MySQLDialectProvider");
|
||||
return new MySQLDialectProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Profile("mssql")
|
||||
public SqlDialectProvider mssqlDialectProvider() {
|
||||
System.out.println("RepositoryTestConfig: Creating MSSQLDialectProvider");
|
||||
return new MSSQLDialectProvider();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,301 @@
|
|||
package de.avatic.lcc.database.dialect;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MSSQLDialectProvider}.
|
||||
*/
|
||||
@DisplayName("MSSQLDialectProvider Tests")
|
||||
class MSSQLDialectProviderTest {
|
||||
|
||||
private MSSQLDialectProvider provider;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
provider = new MSSQLDialectProvider();
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Metadata Tests")
|
||||
class MetadataTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return correct dialect name")
|
||||
void shouldReturnCorrectDialectName() {
|
||||
assertEquals("Microsoft SQL Server", provider.getDialectName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return correct driver class name")
|
||||
void shouldReturnCorrectDriverClassName() {
|
||||
assertEquals("com.microsoft.sqlserver.jdbc.SQLServerDriver", provider.getDriverClassName());
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Pagination Tests")
|
||||
class PaginationTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build correct pagination clause with OFFSET/FETCH")
|
||||
void shouldBuildCorrectPaginationClause() {
|
||||
String result = provider.buildPaginationClause(10, 20);
|
||||
assertEquals("OFFSET ? ROWS FETCH NEXT ? ROWS ONLY", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return pagination parameters in correct order (offset, limit)")
|
||||
void shouldReturnPaginationParametersInCorrectOrder() {
|
||||
Object[] params = provider.getPaginationParameters(10, 20);
|
||||
// MSSQL: offset first, then limit (reversed from MySQL)
|
||||
assertArrayEquals(new Object[]{20, 10}, params);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Upsert Operation Tests")
|
||||
class UpsertOperationTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build correct MERGE statement")
|
||||
void shouldBuildCorrectMergeStatement() {
|
||||
List<String> uniqueCols = Arrays.asList("id", "user_id");
|
||||
List<String> insertCols = Arrays.asList("id", "user_id", "name", "value");
|
||||
List<String> updateCols = Arrays.asList("name", "value");
|
||||
|
||||
String result = provider.buildUpsertStatement("test_table", uniqueCols, insertCols, updateCols);
|
||||
|
||||
assertTrue(result.contains("MERGE INTO test_table AS target"));
|
||||
assertTrue(result.contains("USING (SELECT"));
|
||||
assertTrue(result.contains("ON target.id = source.id AND target.user_id = source.user_id"));
|
||||
assertTrue(result.contains("WHEN MATCHED THEN UPDATE SET"));
|
||||
assertTrue(result.contains("WHEN NOT MATCHED THEN INSERT"));
|
||||
assertTrue(result.contains("name = source.name"));
|
||||
assertTrue(result.contains("value = source.value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build correct conditional INSERT statement")
|
||||
void shouldBuildCorrectInsertIgnoreStatement() {
|
||||
List<String> columns = Arrays.asList("user_id", "group_id");
|
||||
List<String> uniqueCols = Arrays.asList("user_id", "group_id");
|
||||
|
||||
String result = provider.buildInsertIgnoreStatement("mapping_table", columns, uniqueCols);
|
||||
|
||||
assertTrue(result.contains("IF NOT EXISTS"));
|
||||
assertTrue(result.contains("SELECT 1 FROM mapping_table"));
|
||||
assertTrue(result.contains("WHERE user_id = ? AND group_id = ?"));
|
||||
assertTrue(result.contains("INSERT INTO mapping_table (user_id, group_id) VALUES (?, ?)"));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Locking Strategy Tests")
|
||||
class LockingStrategyTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build WITH (UPDLOCK, READPAST) for SKIP LOCKED equivalent")
|
||||
void shouldBuildSelectForUpdateSkipLocked() {
|
||||
String baseQuery = "SELECT * FROM calculation_job WHERE state = 'CREATED'";
|
||||
String result = provider.buildSelectForUpdateSkipLocked(baseQuery);
|
||||
|
||||
assertTrue(result.contains("WITH (UPDLOCK, READPAST)"));
|
||||
assertTrue(result.contains("FROM calculation_job WITH (UPDLOCK, READPAST)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build WITH (UPDLOCK, ROWLOCK) for standard locking")
|
||||
void shouldBuildSelectForUpdate() {
|
||||
String baseQuery = "SELECT * FROM calculation_job WHERE id = ?";
|
||||
String result = provider.buildSelectForUpdate(baseQuery);
|
||||
|
||||
assertTrue(result.contains("WITH (UPDLOCK, ROWLOCK)"));
|
||||
assertTrue(result.contains("FROM calculation_job WITH (UPDLOCK, ROWLOCK)"));
|
||||
assertFalse(result.contains("READPAST"));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Date/Time Function Tests")
|
||||
class DateTimeFunctionTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return GETDATE() for current timestamp")
|
||||
void shouldReturnGetDateForCurrentTimestamp() {
|
||||
assertEquals("GETDATE()", provider.getCurrentTimestamp());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build date subtraction with GETDATE() using DATEADD")
|
||||
void shouldBuildDateSubtractionWithGetDate() {
|
||||
String result = provider.buildDateSubtraction(null, "3", SqlDialectProvider.DateUnit.DAY);
|
||||
assertEquals("DATEADD(DAY, -3, GETDATE())", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build date subtraction with custom base date")
|
||||
void shouldBuildDateSubtractionWithCustomBaseDate() {
|
||||
String result = provider.buildDateSubtraction("calculation_date", "60", SqlDialectProvider.DateUnit.MINUTE);
|
||||
assertEquals("DATEADD(MINUTE, -60, calculation_date)", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build date addition with GETDATE() using DATEADD")
|
||||
void shouldBuildDateAdditionWithGetDate() {
|
||||
String result = provider.buildDateAddition(null, "7", SqlDialectProvider.DateUnit.DAY);
|
||||
assertEquals("DATEADD(DAY, 7, GETDATE())", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build date addition with custom base date")
|
||||
void shouldBuildDateAdditionWithCustomBaseDate() {
|
||||
String result = provider.buildDateAddition("start_date", "1", SqlDialectProvider.DateUnit.MONTH);
|
||||
assertEquals("DATEADD(MONTH, 1, start_date)", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should extract date from column using CAST")
|
||||
void shouldExtractDateFromColumn() {
|
||||
String result = provider.extractDate("created_at");
|
||||
assertEquals("CAST(created_at AS DATE)", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should extract date from expression using CAST")
|
||||
void shouldExtractDateFromExpression() {
|
||||
String result = provider.extractDate("GETDATE()");
|
||||
assertEquals("CAST(GETDATE() AS DATE)", result);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Auto-increment Reset Tests")
|
||||
class AutoIncrementResetTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build DBCC CHECKIDENT reset statement")
|
||||
void shouldBuildAutoIncrementResetStatement() {
|
||||
String result = provider.buildAutoIncrementReset("test_table");
|
||||
assertEquals("DBCC CHECKIDENT ('test_table', RESEED, 0)", result);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Geospatial Distance Tests")
|
||||
class GeospatialDistanceTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build Haversine distance calculation in kilometers")
|
||||
void shouldBuildHaversineDistanceCalculation() {
|
||||
String result = provider.buildHaversineDistance("50.1", "8.6", "node.geo_lat", "node.geo_lng");
|
||||
|
||||
// MSSQL uses 6371 km (not 6371000 m like MySQL)
|
||||
assertTrue(result.contains("6371"));
|
||||
assertFalse(result.contains("6371000")); // Should NOT be in meters
|
||||
assertTrue(result.contains("ACOS"));
|
||||
assertTrue(result.contains("COS"));
|
||||
assertTrue(result.contains("SIN"));
|
||||
assertTrue(result.contains("RADIANS"));
|
||||
assertTrue(result.contains("50.1"));
|
||||
assertTrue(result.contains("8.6"));
|
||||
assertTrue(result.contains("node.geo_lat"));
|
||||
assertTrue(result.contains("node.geo_lng"));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("String/Type Function Tests")
|
||||
class StringTypeFunctionTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build CONCAT with multiple expressions")
|
||||
void shouldBuildConcatWithMultipleExpressions() {
|
||||
String result = provider.buildConcat("first_name", "' '", "last_name");
|
||||
assertEquals("CONCAT(first_name, ' ', last_name)", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build CONCAT with single expression")
|
||||
void shouldBuildConcatWithSingleExpression() {
|
||||
String result = provider.buildConcat("column_name");
|
||||
assertEquals("CONCAT(column_name)", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should cast to string using VARCHAR")
|
||||
void shouldCastToString() {
|
||||
String result = provider.castToString("user_id");
|
||||
assertEquals("CAST(user_id AS VARCHAR(MAX))", result);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Bulk Operation Tests")
|
||||
class BulkOperationTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return INT max value for MSSQL")
|
||||
void shouldReturnMSSQLIntMaxValue() {
|
||||
// MSSQL returns INT max value (not BIGINT)
|
||||
assertEquals("2147483647", provider.getMaxLimitValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should support RETURNING clause via OUTPUT")
|
||||
void shouldSupportReturningClause() {
|
||||
assertTrue(provider.supportsReturningClause());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build OUTPUT clause for RETURNING")
|
||||
void shouldBuildOutputClause() {
|
||||
String result = provider.buildReturningClause("id", "name", "created_at");
|
||||
|
||||
assertEquals("OUTPUT INSERTED.id, INSERTED.name, INSERTED.created_at", result);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Schema/DDL Tests")
|
||||
class SchemaDDLTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return IDENTITY definition")
|
||||
void shouldReturnIdentityDefinition() {
|
||||
String result = provider.getAutoIncrementDefinition();
|
||||
assertEquals("IDENTITY(1,1)", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return DATETIME2 with default for timestamp")
|
||||
void shouldReturnDateTimeWithDefaultDefinition() {
|
||||
String result = provider.getTimestampDefinition();
|
||||
assertEquals("DATETIME2 DEFAULT GETDATE()", result);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Boolean Literal Tests")
|
||||
class BooleanLiteralTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return '1' for boolean true")
|
||||
void shouldReturnOneForBooleanTrue() {
|
||||
assertEquals("1", provider.getBooleanTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return '0' for boolean false")
|
||||
void shouldReturnZeroForBooleanFalse() {
|
||||
assertEquals("0", provider.getBooleanFalse());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -187,11 +187,13 @@ class MySQLDialectProviderTest {
|
|||
class GeospatialDistanceTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build Haversine distance calculation")
|
||||
@DisplayName("Should build Haversine distance calculation in kilometers")
|
||||
void shouldBuildHaversineDistanceCalculation() {
|
||||
String result = provider.buildHaversineDistance("50.1", "8.6", "node.geo_lat", "node.geo_lng");
|
||||
|
||||
assertTrue(result.contains("6371000"));
|
||||
// MySQL now uses 6371 km (not 6371000 m) for consistency with MSSQL
|
||||
assertTrue(result.contains("6371"));
|
||||
assertFalse(result.contains("6371000")); // Should NOT be in meters
|
||||
assertTrue(result.contains("ACOS"));
|
||||
assertTrue(result.contains("COS"));
|
||||
assertTrue(result.contains("SIN"));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
package de.avatic.lcc.repositories;
|
||||
|
||||
import de.avatic.lcc.config.DatabaseTestConfiguration;
|
||||
import de.avatic.lcc.config.RepositoryTestConfig;
|
||||
import de.avatic.lcc.database.dialect.SqlDialectProvider;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
/**
|
||||
* Abstract base class for repository integration tests.
|
||||
* <p>
|
||||
* Provides TestContainers-based database setup for both MySQL and MSSQL.
|
||||
* Tests extending this class will run against the database specified by the active profile.
|
||||
* Flyway migrations from db/migration/{mysql|mssql}/ will be automatically applied.
|
||||
* <p>
|
||||
* Only loads Repository and JDBC beans, not the full application context (no Controllers, no API Services).
|
||||
* <p>
|
||||
* Usage:
|
||||
* <pre>
|
||||
* // Run against MySQL
|
||||
* mvn test -Dspring.profiles.active=test,mysql -Dtest=NodeRepositoryIntegrationTest
|
||||
*
|
||||
* // Run against MSSQL
|
||||
* mvn test -Dspring.profiles.active=test,mssql -Dtest=NodeRepositoryIntegrationTest
|
||||
* </pre>
|
||||
*/
|
||||
@SpringBootTest(
|
||||
classes = {RepositoryTestConfig.class},
|
||||
properties = {
|
||||
"spring.main.web-application-type=none",
|
||||
"spring.autoconfigure.exclude=" +
|
||||
"org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration," +
|
||||
"org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration," +
|
||||
"org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration," +
|
||||
"org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration," +
|
||||
"org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration"
|
||||
}
|
||||
)
|
||||
@Testcontainers
|
||||
@Import(DatabaseTestConfiguration.class)
|
||||
// NOTE: No @ActiveProfiles - profiles come from command line: -Dspring.profiles.active=test,mysql
|
||||
@Transactional // Rollback after each test for isolation
|
||||
public abstract class AbstractRepositoryIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
protected JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
protected SqlDialectProvider dialectProvider;
|
||||
|
||||
/**
|
||||
* Gets the active database profile (mysql or mssql).
|
||||
* Useful for profile-specific test assertions.
|
||||
*/
|
||||
protected String getDatabaseProfile() {
|
||||
return System.getProperty("spring.profiles.active", "mysql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if tests are running against MSSQL.
|
||||
*/
|
||||
protected boolean isMssql() {
|
||||
return getDatabaseProfile().contains("mssql");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if tests are running against MySQL.
|
||||
*/
|
||||
protected boolean isMysql() {
|
||||
return getDatabaseProfile().contains("mysql");
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void baseSetup() {
|
||||
// Common setup logic if needed
|
||||
// Flyway migrations are automatically applied by Spring Boot
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a raw SQL query for test data setup.
|
||||
* Use with caution - prefer using repositories where possible.
|
||||
*/
|
||||
protected void executeRawSql(String sql, Object... params) {
|
||||
jdbcTemplate.update(sql, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts rows in a table.
|
||||
*/
|
||||
protected int countRows(String tableName) {
|
||||
return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM " + tableName, Integer.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
package de.avatic.lcc.repositories;
|
||||
|
||||
import de.avatic.lcc.database.dialect.SqlDialectProvider;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Smoke test to verify TestContainers and Flyway setup.
|
||||
* <p>
|
||||
* Validates:
|
||||
* - TestContainers starts correctly
|
||||
* - Flyway migrations run successfully
|
||||
* - Database contains expected test data
|
||||
* - Correct SqlDialectProvider is loaded
|
||||
* <p>
|
||||
* Run with:
|
||||
* <pre>
|
||||
* mvn test -Dspring.profiles.active=test,mysql -Dtest=DatabaseConfigurationSmokeTest
|
||||
* mvn test -Dspring.profiles.active=test,mssql -Dtest=DatabaseConfigurationSmokeTest
|
||||
* </pre>
|
||||
*/
|
||||
class DatabaseConfigurationSmokeTest extends AbstractRepositoryIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
private SqlDialectProvider dialectProvider;
|
||||
|
||||
@Test
|
||||
void testDatabaseConnectionIsEstablished() {
|
||||
// When: Query database
|
||||
Integer result = jdbcTemplate.queryForObject("SELECT 1", Integer.class);
|
||||
|
||||
// Then: Connection works
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFlywayMigrationsRanSuccessfully() {
|
||||
// When: Check if core tables exist
|
||||
Integer propertySetCount = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM property_set", Integer.class);
|
||||
|
||||
// Then: Table exists (migrations ran)
|
||||
assertNotNull(propertySetCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCountriesWereLoadedFromMigrations() {
|
||||
// When: Count countries
|
||||
Integer countryCount = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM country", Integer.class);
|
||||
|
||||
// Then: Countries exist (V4__Country.sql ran)
|
||||
assertNotNull(countryCount);
|
||||
assertTrue(countryCount > 0, "Countries should be loaded from V4__Country.sql migration");
|
||||
System.out.println("Found " + countryCount + " countries in database");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNodesWereLoadedFromMigrations() {
|
||||
// When: Count nodes
|
||||
Integer nodeCount = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM node", Integer.class);
|
||||
|
||||
// Then: Nodes exist (V5__Nodes.sql ran)
|
||||
assertNotNull(nodeCount);
|
||||
assertTrue(nodeCount > 0, "Nodes should be loaded from V5__Nodes.sql migration");
|
||||
System.out.println("Found " + nodeCount + " nodes in database");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCorrectSqlDialectProviderIsLoaded() {
|
||||
// Debug: Print active profiles
|
||||
String[] activeProfiles = jdbcTemplate.getDataSource() != null ?
|
||||
new String[]{getDatabaseProfile()} : new String[]{};
|
||||
System.out.println("Active Spring profiles from getDatabaseProfile(): " + getDatabaseProfile());
|
||||
System.out.println("System property spring.profiles.active: " + System.getProperty("spring.profiles.active"));
|
||||
|
||||
// When: Check which dialect provider is active
|
||||
String booleanTrue = dialectProvider.getBooleanTrue();
|
||||
|
||||
// Then: Correct provider based on profile
|
||||
if (isMysql()) {
|
||||
assertEquals("TRUE", booleanTrue, "MySQL should use TRUE literal");
|
||||
} else if (isMssql()) {
|
||||
assertEquals("1", booleanTrue, "MSSQL should use 1 literal");
|
||||
}
|
||||
|
||||
System.out.println("Active database profile: " + getDatabaseProfile());
|
||||
System.out.println("Dialect provider class: " + dialectProvider.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBooleanLiteralInQuery() {
|
||||
// When: Query with boolean literal from dialect provider
|
||||
String query = "SELECT COUNT(*) FROM node WHERE is_deprecated = " +
|
||||
dialectProvider.getBooleanFalse();
|
||||
Integer activeNodeCount = jdbcTemplate.queryForObject(query, Integer.class);
|
||||
|
||||
// Then: Query executes without syntax error
|
||||
assertNotNull(activeNodeCount);
|
||||
System.out.println("Active (non-deprecated) nodes: " + activeNodeCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPaginationQuery() {
|
||||
// When: Execute query with pagination (requires ORDER BY in MSSQL)
|
||||
String paginationClause = dialectProvider.buildPaginationClause(5, 0);
|
||||
Object[] paginationParams = dialectProvider.getPaginationParameters(5, 0);
|
||||
|
||||
String query = "SELECT id FROM node ORDER BY id " + paginationClause;
|
||||
var nodeIds = jdbcTemplate.query(query,
|
||||
(rs, rowNum) -> rs.getInt("id"),
|
||||
paginationParams[0], paginationParams[1]);
|
||||
|
||||
// Then: Query executes successfully and returns up to 5 results
|
||||
assertNotNull(nodeIds);
|
||||
assertFalse(nodeIds.isEmpty(), "Should return at least one node");
|
||||
assertTrue(nodeIds.size() <= 5, "Should return at most 5 nodes");
|
||||
System.out.println("Returned " + nodeIds.size() + " nodes with pagination: " + nodeIds);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
package de.avatic.lcc.repositories;
|
||||
|
||||
import de.avatic.lcc.dto.generic.NodeType;
|
||||
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
|
||||
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
|
||||
import de.avatic.lcc.model.db.nodes.Node;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Integration tests for NodeRepository.
|
||||
* <p>
|
||||
* Tests critical functionality across both MySQL and MSSQL:
|
||||
* - Basic CRUD operations
|
||||
* - Pagination with ORDER BY (MSSQL requirement)
|
||||
* - Haversine distance calculations
|
||||
* - Complex search queries
|
||||
* <p>
|
||||
* Run with:
|
||||
* <pre>
|
||||
* mvn test -Dspring.profiles.active=test,mysql -Dtest=NodeRepositoryIntegrationTest
|
||||
* mvn test -Dspring.profiles.active=test,mssql -Dtest=NodeRepositoryIntegrationTest
|
||||
* </pre>
|
||||
*/
|
||||
class NodeRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private NodeRepository nodeRepository;
|
||||
|
||||
@Test
|
||||
void testInsertAndRetrieveNode() {
|
||||
// Given
|
||||
Node node = new Node();
|
||||
node.setName("Test Node");
|
||||
node.setAddress("Test Address 123");
|
||||
node.setGeoLat(new BigDecimal("52.5200"));
|
||||
node.setGeoLng(new BigDecimal("13.4050"));
|
||||
node.setDeprecated(false);
|
||||
node.setCountryId(1); // Assuming country with id=1 exists in Flyway migrations
|
||||
|
||||
// When
|
||||
Integer nodeId = nodeRepository.insert(node);
|
||||
|
||||
// Then
|
||||
assertNotNull(nodeId, "Node ID should not be null");
|
||||
assertTrue(nodeId > 0, "Node ID should be positive");
|
||||
|
||||
Optional<Node> retrieved = nodeRepository.getById(nodeId);
|
||||
assertTrue(retrieved.isPresent(), "Node should be retrievable after creation");
|
||||
assertEquals("Test Node", retrieved.get().getName());
|
||||
assertEquals("Test Address 123", retrieved.get().getAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateNode() {
|
||||
// Given: Create a node first
|
||||
Node node = createTestNode("Original Name", "Original Address", "50.0", "10.0");
|
||||
Integer nodeId = nodeRepository.insert(node);
|
||||
|
||||
// When: Update the node
|
||||
Node updatedNode = nodeRepository.getById(nodeId).orElseThrow();
|
||||
updatedNode.setName("Updated Name");
|
||||
updatedNode.setAddress("Updated Address");
|
||||
nodeRepository.update(updatedNode);
|
||||
|
||||
// Then: Verify update
|
||||
Node result = nodeRepository.getById(nodeId).orElseThrow();
|
||||
assertEquals("Updated Name", result.getName());
|
||||
assertEquals("Updated Address", result.getAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeprecateNode() {
|
||||
// Given: Create a node
|
||||
Node node = createTestNode("Node to Deprecate", "Address", "50.0", "10.0");
|
||||
Integer nodeId = nodeRepository.insert(node);
|
||||
|
||||
// When: Deprecate the node
|
||||
nodeRepository.setDeprecatedById(nodeId);
|
||||
|
||||
// Then: Verify node is deprecated
|
||||
Node deprecated = nodeRepository.getById(nodeId).orElseThrow();
|
||||
assertTrue(deprecated.getDeprecated(), "Node should be marked as deprecated");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListNodesWithPagination() {
|
||||
// Given: Create multiple nodes
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
Node node = createTestNode("Pagination Node " + i, "Address " + i, "50." + i, "10." + i);
|
||||
nodeRepository.insert(node);
|
||||
}
|
||||
|
||||
// When: List nodes with pagination (page 1, size 3)
|
||||
SearchQueryPagination pagination = new SearchQueryPagination(1, 3);
|
||||
SearchQueryResult<Node> result = nodeRepository.listNodes(null, false, pagination);
|
||||
|
||||
// Then: Verify pagination works (ORDER BY is required for MSSQL)
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.toList());
|
||||
assertTrue(result.toList().size() <= 3, "Should return at most 3 nodes per page");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSearchNodeWithFilter() {
|
||||
// Given: Create nodes with different names
|
||||
Node node1 = createTestNode("Berlin Node Test", "Berlin Street 1", "52.5200", "13.4050");
|
||||
Node node2 = createTestNode("Munich Node Test", "Munich Street 1", "48.1351", "11.5820");
|
||||
Node node3 = createTestNode("Hamburg Node Test", "Hamburg Street 1", "53.5511", "9.9937");
|
||||
nodeRepository.insert(node1);
|
||||
nodeRepository.insert(node2);
|
||||
nodeRepository.insert(node3);
|
||||
|
||||
// When: Search for nodes containing "Berlin"
|
||||
List<Node> results = nodeRepository.searchNode("Berlin", 10, null, false);
|
||||
|
||||
// Then: Should find Berlin node
|
||||
assertFalse(results.isEmpty(), "Should find at least one node");
|
||||
assertTrue(results.stream().anyMatch(n -> n.getName().contains("Berlin")),
|
||||
"Should contain Berlin node");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetByDistanceWithHaversineFormula() {
|
||||
// Given: Create a reference node (Berlin)
|
||||
Node referenceNode = createTestNode("Berlin Distance Test", "Berlin Center", "52.5200", "13.4050");
|
||||
referenceNode.setUserNode(false);
|
||||
Integer refId = nodeRepository.insert(referenceNode);
|
||||
referenceNode.setId(refId);
|
||||
|
||||
// Create a nearby node (Potsdam, ~30km from Berlin)
|
||||
Node nearbyNode = createTestNode("Potsdam Distance Test", "Potsdam Center", "52.3906", "13.0645");
|
||||
nodeRepository.insert(nearbyNode);
|
||||
|
||||
// Create a far node (Munich, ~500km from Berlin)
|
||||
Node farNode = createTestNode("Munich Distance Test", "Munich Center", "48.1351", "11.5820");
|
||||
nodeRepository.insert(farNode);
|
||||
|
||||
// When: Get nodes within 100km radius
|
||||
// The Haversine formula returns distance in kilometers for both MySQL and MSSQL
|
||||
List<Node> nodesWithin100km = nodeRepository.getByDistance(referenceNode, 100);
|
||||
|
||||
// Then: Should find nearby node but not far node
|
||||
assertNotNull(nodesWithin100km);
|
||||
assertTrue(nodesWithin100km.stream().anyMatch(n -> n.getName().contains("Potsdam")),
|
||||
"Should find Potsdam (30km away)");
|
||||
assertFalse(nodesWithin100km.stream().anyMatch(n -> n.getName().contains("Munich")),
|
||||
"Should not find Munich (500km away)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetByDistanceExcludingReferenceNode() {
|
||||
// Given: Create reference node
|
||||
Node referenceNode = createTestNode("Reference Node Distance", "Ref Address", "50.0", "10.0");
|
||||
referenceNode.setUserNode(false);
|
||||
Integer refId = nodeRepository.insert(referenceNode);
|
||||
referenceNode.setId(refId);
|
||||
|
||||
// Create nearby node
|
||||
Node nearbyNode = createTestNode("Nearby Node Distance", "Nearby Address", "50.1", "10.1");
|
||||
nodeRepository.insert(nearbyNode);
|
||||
|
||||
// When: Get nodes within large radius
|
||||
List<Node> results = nodeRepository.getByDistance(referenceNode, 1000);
|
||||
|
||||
// Then: Reference node itself should be excluded (via id != ?)
|
||||
assertFalse(results.stream().anyMatch(n -> n.getId().equals(refId)),
|
||||
"Reference node should be excluded from results");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBooleanLiteralCompatibility() {
|
||||
// Given: Create deprecated and non-deprecated nodes
|
||||
Node deprecatedNode = createTestNode("Deprecated Boolean Test", "Addr1", "50.0", "10.0");
|
||||
Integer depId = nodeRepository.insert(deprecatedNode);
|
||||
nodeRepository.setDeprecatedById(depId);
|
||||
|
||||
Node activeNode = createTestNode("Active Boolean Test", "Addr2", "50.1", "10.1");
|
||||
nodeRepository.insert(activeNode);
|
||||
|
||||
// When: Search excluding deprecated nodes
|
||||
List<Node> activeNodes = nodeRepository.searchNode("Boolean Test", 100, null, true);
|
||||
|
||||
// Then: Should not include deprecated node
|
||||
assertFalse(activeNodes.stream().anyMatch(n -> n.getId().equals(depId)),
|
||||
"Should exclude deprecated nodes when excludeDeprecated=true");
|
||||
}
|
||||
|
||||
// ========== Helper Methods ==========
|
||||
|
||||
private Node createTestNode(String name, String address, String lat, String lng) {
|
||||
Node node = new Node();
|
||||
node.setName(name);
|
||||
node.setAddress(address);
|
||||
node.setGeoLat(new BigDecimal(lat));
|
||||
node.setGeoLng(new BigDecimal(lng));
|
||||
node.setDeprecated(false);
|
||||
node.setCountryId(1); // Assuming country id=1 exists
|
||||
node.setUserNode(false);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
17
src/test/resources/application-mssql.properties
Normal file
17
src/test/resources/application-mssql.properties
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# MSSQL Test Profile Configuration
|
||||
# Activate with: mvn test -Dspring.profiles.active=test,mssql
|
||||
|
||||
# Flyway Migration - MSSQL specific
|
||||
spring.flyway.locations=classpath:db/migration/mssql
|
||||
|
||||
# TestContainers will automatically provide:
|
||||
# - spring.datasource.url
|
||||
# - spring.datasource.username
|
||||
# - spring.datasource.password
|
||||
# - spring.datasource.driver-class-name
|
||||
|
||||
# Disable calculation job processor in tests
|
||||
calculation.job.processor.enabled=false
|
||||
|
||||
# Disable Azure Maps API calls in tests
|
||||
# (Mock these services in test classes if needed)
|
||||
17
src/test/resources/application-mysql.properties
Normal file
17
src/test/resources/application-mysql.properties
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# MySQL Test Profile Configuration
|
||||
# Activate with: mvn test -Dspring.profiles.active=test,mysql
|
||||
|
||||
# Flyway Migration - MySQL specific
|
||||
spring.flyway.locations=classpath:db/migration/mysql
|
||||
|
||||
# TestContainers will automatically provide:
|
||||
# - spring.datasource.url
|
||||
# - spring.datasource.username
|
||||
# - spring.datasource.password
|
||||
# - spring.datasource.driver-class-name
|
||||
|
||||
# Disable calculation job processor in tests
|
||||
calculation.job.processor.enabled=false
|
||||
|
||||
# Disable Azure Maps API calls in tests
|
||||
# (Mock these services in test classes if needed)
|
||||
|
|
@ -1,12 +1,40 @@
|
|||
spring.config.import=classpath:env.properties
|
||||
# Test Configuration for TestContainers-based Integration Tests
|
||||
# DataSource is automatically configured by @ServiceConnection from TestContainers
|
||||
|
||||
spring.application.name=lcc
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/${DB_DATABASE}
|
||||
spring.datasource.username=${DB_USER}
|
||||
spring.datasource.password=${DB_PASSWORD}
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.sql.init.mode=always
|
||||
spring.sql.init.continue-on-error=false
|
||||
spring.sql.init.schema-locations=classpath:schema.sql
|
||||
|
||||
# Disable env.properties import for tests (TestContainers provides DB config)
|
||||
# spring.config.import=classpath:env.properties
|
||||
|
||||
# Disable schema.sql - we use Flyway migrations instead
|
||||
spring.sql.init.mode=never
|
||||
|
||||
# Flyway configuration - migrations will run automatically
|
||||
spring.flyway.enabled=true
|
||||
spring.flyway.baseline-on-migrate=true
|
||||
spring.flyway.clean-disabled=false
|
||||
# Note: spring.flyway.locations is set in application-mysql.properties or application-mssql.properties
|
||||
|
||||
# Security disabled for integration tests
|
||||
spring.autoconfigure.exclude=\
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration
|
||||
|
||||
# Disable Azure AD for tests
|
||||
spring.cloud.azure.active-directory.enabled=false
|
||||
|
||||
# Disable async processing in tests (EUTaxationApiService uses @Async)
|
||||
spring.task.execution.pool.core-size=0
|
||||
spring.task.scheduling.enabled=false
|
||||
|
||||
# Logging
|
||||
logging.level.org.flywaydb=INFO
|
||||
logging.level.org.testcontainers=INFO
|
||||
logging.level.de.avatic.lcc=DEBUG
|
||||
logging.level.org.springframework.jdbc=DEBUG
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue