Refactored and extended integration tests for repositories; added data cleanup methods, improved test coverage for property date handling, and adjusted SQL queries for validity and property set logic. Removed unused dependencies in NomenclatureRepository.

This commit is contained in:
Jan 2026-01-27 22:58:39 +01:00
parent 1a5a00e111
commit 3f8453f93b
6 changed files with 160 additions and 59 deletions

View file

@ -12,12 +12,10 @@ public class NomenclatureRepository {
private final JdbcTemplate jdbcTemplate;
private final SqlDialectProvider dialectProvider;
private final EUTaxationApiService eUTaxationApiService;
public NomenclatureRepository(JdbcTemplate jdbcTemplate, SqlDialectProvider dialectProvider, EUTaxationApiService eUTaxationApiService) {
public NomenclatureRepository(JdbcTemplate jdbcTemplate, SqlDialectProvider dialectProvider) {
this.jdbcTemplate = jdbcTemplate;
this.dialectProvider = dialectProvider;
this.eUTaxationApiService = eUTaxationApiService;
}
public List<String> searchHsCode(String search) {

View file

@ -64,8 +64,8 @@ public class ValidityPeriodRepository {
*/
@Transactional
public Optional<Integer> getPeriodId(LocalDateTime validAt) {
String query = "SELECT id FROM validity_period WHERE ? BETWEEN start_date AND end_date";
return Optional.ofNullable(jdbcTemplate.query(query, (rs) -> rs.next() ? rs.getInt("id") : null, validAt));
String query = "SELECT id FROM validity_period WHERE start_date <= ? AND (end_date IS NULL OR end_date >= ?)";
return Optional.ofNullable(jdbcTemplate.query(query, (rs) -> rs.next() ? rs.getInt("id") : null, validAt, validAt));
}
/**

View file

@ -47,6 +47,11 @@ class CountryPropertyRepositoryIntegrationTest extends AbstractRepositoryIntegra
@BeforeEach
void setupTestData() {
// Clean up any property data from other tests
jdbcTemplate.update("DELETE FROM system_property");
jdbcTemplate.update("DELETE FROM country_property");
jdbcTemplate.update("DELETE FROM property_set");
// Use existing country (id=1 should exist from migrations)
testCountryId = 1;

View file

@ -46,6 +46,11 @@ class PropertyRepositoryIntegrationTest extends AbstractRepositoryIntegrationTes
@BeforeEach
void setupTestData() {
// Clean up any property data from other tests
jdbcTemplate.update("DELETE FROM system_property");
jdbcTemplate.update("DELETE FROM country_property");
jdbcTemplate.update("DELETE FROM property_set");
// Get property type ID for existing mapping
testPropertyTypeId = getPropertyTypeId(testMappingId.name());

View file

@ -3,10 +3,13 @@ package de.avatic.lcc.repositories.properties;
import de.avatic.lcc.model.db.properties.PropertySet;
import de.avatic.lcc.model.db.rates.ValidityPeriodState;
import de.avatic.lcc.repositories.AbstractRepositoryIntegrationTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@ -19,7 +22,6 @@ import static org.junit.jupiter.api.Assertions.*;
* - Draft creation and retrieval
* - State transitions (DRAFT VALID EXPIRED INVALID)
* - Date-based queries with dialect-specific date extraction
* - Pagination compatibility
* - Timestamp handling
* <p>
* Run with:
@ -33,6 +35,14 @@ class PropertySetRepositoryIntegrationTest extends AbstractRepositoryIntegration
@Autowired
private PropertySetRepository propertySetRepository;
@BeforeEach
void cleanupPropertySets() {
// Clean up any property sets from other tests
jdbcTemplate.update("DELETE FROM system_property");
jdbcTemplate.update("DELETE FROM country_property");
jdbcTemplate.update("DELETE FROM property_set");
}
@Test
void testGetDraftSet() {
// When: Get draft set (creates if doesn't exist)
@ -73,7 +83,7 @@ class PropertySetRepositoryIntegrationTest extends AbstractRepositoryIntegration
@Test
void testListPropertySets() {
// Given: Ensure draft exists
// Given: Create draft
propertySetRepository.getDraftSet();
// When: List all property sets
@ -102,6 +112,7 @@ class PropertySetRepositoryIntegrationTest extends AbstractRepositoryIntegration
PropertySet nowValid = propertySetRepository.getById(draftId);
assertEquals(ValidityPeriodState.VALID, nowValid.getState());
assertNotNull(nowValid.getStartDate());
assertNull(nowValid.getEndDate(), "Valid set should not have end date yet");
// New draft should exist
PropertySet newDraft = propertySetRepository.getDraftSet();
@ -140,47 +151,38 @@ class PropertySetRepositoryIntegrationTest extends AbstractRepositoryIntegration
assertEquals(ValidityPeriodState.VALID, validSet.getState());
}
@Test
void testGetValidSetWhenNone() {
// When: Get valid set when none exists (only draft)
Optional<PropertySet> validSet = propertySetRepository.getValidSet();
// Then: Should be empty
assertFalse(validSet.isPresent(), "Should not have valid set when only draft exists");
}
@Test
void testApplyDraftExpiresOldValid() {
// Given: Apply draft to create valid set
propertySetRepository.getDraftSet();
propertySetRepository.applyDraft();
// Given: Manually create a VALID set (to avoid timing issues with applyDraft)
LocalDateTime pastStart = LocalDateTime.now().minusDays(10);
Integer firstValidId = createTestPropertySet(ValidityPeriodState.VALID, pastStart, null);
Integer firstValidId = propertySetRepository.getValidSetId();
// Apply again to expire first valid
// When: Apply draft (should expire the existing VALID set)
propertySetRepository.getDraftSet(); // Creates draft
propertySetRepository.applyDraft();
// Then: First valid should now be expired
PropertySet expired = propertySetRepository.getById(firstValidId);
assertEquals(ValidityPeriodState.EXPIRED, expired.getState());
assertNotNull(expired.getEndDate(), "Expired set should have end date");
assertTrue(expired.getEndDate().isAfter(expired.getStartDate()),
"End date must be after start date");
}
@Test
void testInvalidateById() {
// Given: Create expired property set
propertySetRepository.getDraftSet();
propertySetRepository.applyDraft();
Integer firstValidId = propertySetRepository.getValidSetId();
propertySetRepository.applyDraft(); // Expires first valid
// Given: Create expired property set manually
LocalDateTime pastStart = LocalDateTime.now().minusDays(30);
LocalDateTime pastEnd = LocalDateTime.now().minusDays(15);
Integer expiredId = createTestPropertySet(ValidityPeriodState.EXPIRED, pastStart, pastEnd);
// When: Invalidate expired set
boolean invalidated = propertySetRepository.invalidateById(firstValidId);
boolean invalidated = propertySetRepository.invalidateById(expiredId);
// Then: Should be invalidated
assertTrue(invalidated, "Should successfully invalidate expired property set");
PropertySet invalidSet = propertySetRepository.getById(firstValidId);
PropertySet invalidSet = propertySetRepository.getById(expiredId);
assertEquals(ValidityPeriodState.INVALID, invalidSet.getState());
}
@ -249,9 +251,9 @@ class PropertySetRepositoryIntegrationTest extends AbstractRepositoryIntegration
@Test
void testGetByDate() {
// Given: Apply draft to create valid set
propertySetRepository.getDraftSet();
propertySetRepository.applyDraft();
// Given: Create valid set manually with past date (to avoid timing issues)
LocalDateTime validStart = LocalDateTime.now().minusDays(5);
Integer validId = createTestPropertySet(ValidityPeriodState.VALID, validStart, null);
// When: Get by today's date
LocalDate today = LocalDate.now();
@ -260,34 +262,55 @@ class PropertySetRepositoryIntegrationTest extends AbstractRepositoryIntegration
// Then: Should find valid set
assertTrue(result.isPresent(), "Should find property set for today");
assertEquals(ValidityPeriodState.VALID, result.get().getState());
assertEquals(validId, result.get().getId());
}
@Test
void testGetByDateNotFound() {
// Given: Only draft exists (no valid set)
propertySetRepository.getDraftSet();
void testGetByDatePastDate() {
// Given: Create expired property set in the past
LocalDateTime pastStart = LocalDateTime.now().minusDays(30);
LocalDateTime pastEnd = LocalDateTime.now().minusDays(15);
Integer expiredId = createTestPropertySet(ValidityPeriodState.EXPIRED, pastStart, pastEnd);
// When: Get by future date
LocalDate futureDate = LocalDate.now().plusYears(10);
Optional<PropertySet> result = propertySetRepository.getByDate(futureDate);
// When: Get by date within past range
LocalDate pastDate = LocalDate.now().minusDays(20);
Optional<PropertySet> result = propertySetRepository.getByDate(pastDate);
// Then: Should not find (draft is not in date range)
assertFalse(result.isPresent(), "Should not find property set for future date");
// Then: Should find expired set
assertTrue(result.isPresent(), "Should find property set for past date");
assertEquals(expiredId, result.get().getId());
}
@Test
void testGetByDateOrdering() {
// Given: Multiple property sets
propertySetRepository.getDraftSet();
propertySetRepository.applyDraft(); // Creates first valid
propertySetRepository.applyDraft(); // Expires first, creates second valid
// Given: Create multiple property sets manually
LocalDateTime old = LocalDateTime.now().minusDays(20);
LocalDateTime recent = LocalDateTime.now().minusDays(1);
// When: Get by today's date
Integer oldExpired = createTestPropertySet(ValidityPeriodState.EXPIRED, old, recent);
Integer recentValid = createTestPropertySet(ValidityPeriodState.VALID, recent, null);
// When: Get by today's date (recent VALID covers today, old EXPIRED does not)
LocalDate today = LocalDate.now();
Optional<PropertySet> result = propertySetRepository.getByDate(today);
// Then: Should return most recent (ORDER BY start_date DESC with LIMIT 1)
// Then: Should return the VALID one
assertTrue(result.isPresent());
assertEquals(ValidityPeriodState.VALID, result.get().getState());
assertEquals(recentValid, result.get().getId());
}
// ========== Helper Methods ==========
private Integer createTestPropertySet(ValidityPeriodState state, LocalDateTime startDate, LocalDateTime endDate) {
String sql = "INSERT INTO property_set (state, start_date, end_date) VALUES (?, ?, ?)";
Timestamp startTs = Timestamp.valueOf(startDate);
Timestamp endTs = endDate != null ? Timestamp.valueOf(endDate) : null;
executeRawSql(sql, state.name(), startTs, endTs);
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
return jdbcTemplate.queryForObject(selectSql, Integer.class);
}
}

View file

@ -22,7 +22,6 @@ import static org.junit.jupiter.api.Assertions.*;
* - CRUD operations
* - State management (DRAFT, VALID, EXPIRED, INVALID)
* - Date-based queries with dialect-specific date extraction
* - Pagination compatibility
* - Timestamp handling
* <p>
* Run with:
@ -41,6 +40,18 @@ class ValidityPeriodRepositoryIntegrationTest extends AbstractRepositoryIntegrat
@BeforeEach
void setupTestData() {
// Clean up any validity periods from other tests
// Must delete in correct order due to foreign key constraints
jdbcTemplate.update("DELETE FROM sys_error_trace_item");
jdbcTemplate.update("DELETE FROM calculation_job_route_section");
jdbcTemplate.update("DELETE FROM calculation_job_destination");
jdbcTemplate.update("DELETE FROM sys_error");
jdbcTemplate.update("DELETE FROM calculation_job");
jdbcTemplate.update("DELETE FROM container_rate");
jdbcTemplate.update("DELETE FROM country_matrix_rate");
jdbcTemplate.update("DELETE FROM bulk_operation");
jdbcTemplate.update("DELETE FROM validity_period");
// Create test validity periods
testValidPeriodId = createTestValidityPeriod(ValidityPeriodState.VALID,
LocalDateTime.now().minusDays(1), null);
@ -85,6 +96,7 @@ class ValidityPeriodRepositoryIntegrationTest extends AbstractRepositoryIntegrat
// Then: Should find valid period
assertTrue(period.isPresent(), "Should have a VALID period");
assertEquals(ValidityPeriodState.VALID, period.get().getState());
assertEquals(testValidPeriodId, period.get().getId());
}
@Test
@ -134,9 +146,25 @@ class ValidityPeriodRepositoryIntegrationTest extends AbstractRepositoryIntegrat
assertEquals(testValidPeriodId, periodId.get());
}
@Test
void testGetPeriodIdForPastDate() {
// Given: Time within expired period range
LocalDateTime pastTime = LocalDateTime.now().minusDays(20);
// When: Get period ID
Optional<Integer> periodId = validityPeriodRepository.getPeriodId(pastTime);
// Then: Should find expired period
assertTrue(periodId.isPresent(), "Should find period for past timestamp");
assertEquals(testExpiredPeriodId, periodId.get());
}
@Test
void testGetPeriodIdNotFound() {
// Given: Time far in the future
// Given: Only expired periods (create valid period with end date so future is not covered)
jdbcTemplate.update("DELETE FROM validity_period WHERE state = 'VALID'");
// Time far in the future (no period covers it since all have end dates)
LocalDateTime futureTime = LocalDateTime.now().plusYears(10);
// When: Get period ID
@ -157,11 +185,29 @@ class ValidityPeriodRepositoryIntegrationTest extends AbstractRepositoryIntegrat
// Then: Should find valid period
assertTrue(period.isPresent(), "Should find period for today");
assertEquals(ValidityPeriodState.VALID, period.get().getState());
assertEquals(testValidPeriodId, period.get().getId());
}
@Test
void testGetByDatePast() {
// Given: Date within expired period range
LocalDate pastDate = LocalDate.now().minusDays(20);
// When: Get by date
Optional<ValidityPeriod> period = validityPeriodRepository.getByDate(pastDate);
// Then: Should find expired period
assertTrue(period.isPresent(), "Should find period for past date");
assertEquals(ValidityPeriodState.EXPIRED, period.get().getState());
assertEquals(testExpiredPeriodId, period.get().getId());
}
@Test
void testGetByDateNotFound() {
// Given: Date far in the future
// Given: Only expired periods (create valid period with end date so future is not covered)
jdbcTemplate.update("DELETE FROM validity_period WHERE state = 'VALID'");
// Date far in the future (no period covers it since all have end dates)
LocalDate futureDate = LocalDate.now().plusYears(10);
// When: Get by date
@ -173,11 +219,11 @@ class ValidityPeriodRepositoryIntegrationTest extends AbstractRepositoryIntegrat
@Test
void testHasRateDrafts() {
// Given: Create draft period
// Given: Create draft period (but no associated rates)
Integer draftId = createTestValidityPeriod(ValidityPeriodState.DRAFT,
LocalDateTime.now(), null);
// When: Check if has rate drafts (requires associated rates in container_rate or country_matrix_rate)
// When: Check if has rate drafts
boolean hasDrafts = validityPeriodRepository.hasRateDrafts();
// Then: Should be false (no rates associated)
@ -186,7 +232,7 @@ class ValidityPeriodRepositoryIntegrationTest extends AbstractRepositoryIntegrat
@Test
void testHasMatrixRateDrafts() {
// Given: Create draft period
// Given: Create draft period (but no associated matrix rates)
Integer draftId = createTestValidityPeriod(ValidityPeriodState.DRAFT,
LocalDateTime.now(), null);
@ -199,7 +245,7 @@ class ValidityPeriodRepositoryIntegrationTest extends AbstractRepositoryIntegrat
@Test
void testHasContainerRateDrafts() {
// Given: Create draft period
// Given: Create draft period (but no associated container rates)
Integer draftId = createTestValidityPeriod(ValidityPeriodState.DRAFT,
LocalDateTime.now(), null);
@ -227,17 +273,41 @@ class ValidityPeriodRepositoryIntegrationTest extends AbstractRepositoryIntegrat
@Test
void testGetByDateOrderingWithPagination() {
// Given: Multiple periods with overlapping dates
// Given: Multiple periods with overlapping date ranges
// testExpiredPeriodId covers: -30 to -15 days
// Create another period that also covers -20 days (overlaps with testExpiredPeriodId)
Integer period2 = createTestValidityPeriod(ValidityPeriodState.EXPIRED,
LocalDateTime.now().minusDays(60), LocalDateTime.now().minusDays(45));
LocalDateTime.now().minusDays(25), LocalDateTime.now().minusDays(10));
// When: Get by date (should use ORDER BY start_date DESC with pagination)
LocalDate searchDate = LocalDate.now().minusDays(50);
// When: Get by date that both periods cover (should use ORDER BY start_date DESC with LIMIT 1)
LocalDate searchDate = LocalDate.now().minusDays(20);
Optional<ValidityPeriod> result = validityPeriodRepository.getByDate(searchDate);
// Then: Should return the most recent (LIMIT 1 with ORDER BY DESC)
// Then: Should return the most recent one (period2 has more recent start_date)
assertTrue(result.isPresent());
// Should be the one with most recent start_date
assertEquals(period2, result.get().getId(), "Should return period with most recent start_date");
}
@Test
void testMultiplePeriods() {
// Given: Create multiple periods
Integer draft = createTestValidityPeriod(ValidityPeriodState.DRAFT,
LocalDateTime.now(), null);
Integer invalid = createTestValidityPeriod(ValidityPeriodState.INVALID,
LocalDateTime.now().minusDays(100), LocalDateTime.now().minusDays(90));
// When: List all periods
List<ValidityPeriod> periods = validityPeriodRepository.listPeriods();
// Then: Should have all 5 periods (2 from setup + 3 created here)
assertTrue(periods.size() >= 4, "Should have at least 4 validity periods");
// Verify all states are present
List<ValidityPeriodState> states = periods.stream().map(ValidityPeriod::getState).toList();
assertTrue(states.contains(ValidityPeriodState.VALID));
assertTrue(states.contains(ValidityPeriodState.EXPIRED));
assertTrue(states.contains(ValidityPeriodState.DRAFT));
assertTrue(states.contains(ValidityPeriodState.INVALID));
}
// ========== Helper Methods ==========