Added integration tests for UserNodeRepository, MaterialRepository, NomenclatureRepository, and PackagingDimensionRepository for MySQL and MSSQL.
This commit is contained in:
parent
919c9d0499
commit
6fc0839320
6 changed files with 1049 additions and 34 deletions
|
|
@ -61,7 +61,7 @@ public class PackagingRepository {
|
||||||
Object[] paginationParams = dialectProvider.getPaginationParameters(pagination.getLimit(), pagination.getOffset());
|
Object[] paginationParams = dialectProvider.getPaginationParameters(pagination.getLimit(), pagination.getOffset());
|
||||||
|
|
||||||
var params = new ArrayList<Object>();
|
var params = new ArrayList<Object>();
|
||||||
params.add(excludeDeprecated);
|
// Note: excludeDeprecated is not added as parameter - it's inserted as boolean literal in buildQuery()
|
||||||
if (materialId != null) {
|
if (materialId != null) {
|
||||||
params.add(materialId);
|
params.add(materialId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,351 @@
|
||||||
|
package de.avatic.lcc.repositories;
|
||||||
|
|
||||||
|
import de.avatic.lcc.model.db.materials.Material;
|
||||||
|
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
|
||||||
|
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for MaterialRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - CRUD operations (Create, Read, Update, Delete)
|
||||||
|
* - Pagination with ORDER BY (MSSQL requirement)
|
||||||
|
* - Search with filters (name and part_number)
|
||||||
|
* - Boolean literal compatibility (deprecated filtering)
|
||||||
|
* - Bulk operations (getByPartNumbers, deleteByIds, findMissingIds)
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=MaterialRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=MaterialRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class MaterialRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MaterialRepository materialRepository;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsertAndRetrieve() {
|
||||||
|
// Given: Create material
|
||||||
|
Material material = createTestMaterial("TEST-001", "Test Material 1");
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
materialRepository.insert(material);
|
||||||
|
|
||||||
|
// When: Retrieve by part number
|
||||||
|
Optional<Material> retrieved = materialRepository.getByPartNumber("TEST-001");
|
||||||
|
|
||||||
|
// Then: Should retrieve successfully
|
||||||
|
assertTrue(retrieved.isPresent(), "Material should be retrievable after insert");
|
||||||
|
assertEquals("TEST-001", retrieved.get().getPartNumber());
|
||||||
|
assertEquals("Test Material 1", retrieved.get().getName());
|
||||||
|
assertFalse(retrieved.get().getDeprecated());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdate() {
|
||||||
|
// Given: Insert material
|
||||||
|
Material material = createTestMaterial("TEST-002", "Original Name");
|
||||||
|
materialRepository.insert(material);
|
||||||
|
|
||||||
|
// When: Update material
|
||||||
|
Material toUpdate = materialRepository.getByPartNumber("TEST-002").orElseThrow();
|
||||||
|
toUpdate.setName("Updated Name");
|
||||||
|
toUpdate.setHsCode("12345678901");
|
||||||
|
materialRepository.update(toUpdate);
|
||||||
|
|
||||||
|
// Then: Verify update
|
||||||
|
Material updated = materialRepository.getById(toUpdate.getId()).orElseThrow();
|
||||||
|
assertEquals("Updated Name", updated.getName());
|
||||||
|
assertEquals("12345678901", updated.getHsCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateByPartNumber() {
|
||||||
|
// Given: Insert material
|
||||||
|
Material material = createTestMaterial("TEST-003", "Original Name");
|
||||||
|
materialRepository.insert(material);
|
||||||
|
|
||||||
|
// When: Update by part number
|
||||||
|
Material toUpdate = materialRepository.getByPartNumber("TEST-003").orElseThrow();
|
||||||
|
toUpdate.setName("Updated via PartNumber");
|
||||||
|
materialRepository.updateByPartNumber(toUpdate);
|
||||||
|
|
||||||
|
// Then: Verify update
|
||||||
|
Material updated = materialRepository.getByPartNumber("TEST-003").orElseThrow();
|
||||||
|
assertEquals("Updated via PartNumber", updated.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSetDeprecatedById() {
|
||||||
|
// Given: Insert material
|
||||||
|
Material material = createTestMaterial("TEST-004", "Material to Deprecate");
|
||||||
|
materialRepository.insert(material);
|
||||||
|
Integer materialId = materialRepository.getByPartNumber("TEST-004").orElseThrow().getId();
|
||||||
|
|
||||||
|
// When: Deprecate
|
||||||
|
Optional<Integer> result = materialRepository.setDeprecatedById(materialId);
|
||||||
|
|
||||||
|
// Then: Should be deprecated
|
||||||
|
assertTrue(result.isPresent());
|
||||||
|
|
||||||
|
// getById() excludes deprecated
|
||||||
|
Optional<Material> deprecated = materialRepository.getById(materialId);
|
||||||
|
assertFalse(deprecated.isPresent(), "getById() should exclude deprecated materials");
|
||||||
|
|
||||||
|
// But getByIdIncludeDeprecated() should find it
|
||||||
|
Optional<Material> includingDeprecated = materialRepository.getByIdIncludeDeprecated(materialId);
|
||||||
|
assertTrue(includingDeprecated.isPresent(), "getByIdIncludeDeprecated() should find deprecated materials");
|
||||||
|
assertTrue(includingDeprecated.get().getDeprecated());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteById() {
|
||||||
|
// Given: Insert material
|
||||||
|
Material material = createTestMaterial("TEST-005", "Material to Delete");
|
||||||
|
materialRepository.insert(material);
|
||||||
|
Integer materialId = materialRepository.getByPartNumber("TEST-005").orElseThrow().getId();
|
||||||
|
|
||||||
|
// When: Delete (soft delete - sets deprecated)
|
||||||
|
materialRepository.deleteById(materialId);
|
||||||
|
|
||||||
|
// Then: Should be deprecated
|
||||||
|
Optional<Material> deleted = materialRepository.getById(materialId);
|
||||||
|
assertFalse(deleted.isPresent(), "Deleted material should not be retrievable via getById()");
|
||||||
|
|
||||||
|
Optional<Material> includingDeleted = materialRepository.getByIdIncludeDeprecated(materialId);
|
||||||
|
assertTrue(includingDeleted.isPresent());
|
||||||
|
assertTrue(includingDeleted.get().getDeprecated());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListMaterialsWithPagination() {
|
||||||
|
// Given: Insert multiple materials
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
Material material = createTestMaterial("PAGE-" + String.format("%03d", i), "Pagination Material " + i);
|
||||||
|
materialRepository.insert(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When: List with pagination (page 1, size 3)
|
||||||
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 3);
|
||||||
|
SearchQueryResult<Material> result = materialRepository.listMaterials(
|
||||||
|
Optional.empty(), false, pagination
|
||||||
|
);
|
||||||
|
|
||||||
|
// Then: Verify pagination works
|
||||||
|
assertNotNull(result);
|
||||||
|
assertNotNull(result.toList());
|
||||||
|
assertTrue(result.toList().size() <= 3, "Should return at most 3 materials per page");
|
||||||
|
assertTrue(result.getTotalElements() >= 5, "Should have at least 5 materials total");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListMaterialsWithFilter() {
|
||||||
|
// Given: Insert materials with different names
|
||||||
|
Material material1 = createTestMaterial("FILTER-001", "Special Widget");
|
||||||
|
materialRepository.insert(material1);
|
||||||
|
|
||||||
|
Material material2 = createTestMaterial("FILTER-002", "Normal Component");
|
||||||
|
materialRepository.insert(material2);
|
||||||
|
|
||||||
|
Material material3 = createTestMaterial("FILTER-003", "Special Gadget");
|
||||||
|
materialRepository.insert(material3);
|
||||||
|
|
||||||
|
// When: Search for "Special"
|
||||||
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
||||||
|
SearchQueryResult<Material> result = materialRepository.listMaterials(
|
||||||
|
Optional.of("SPECIAL"), false, pagination
|
||||||
|
);
|
||||||
|
|
||||||
|
// Then: Should find materials with "Special" in name
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.toList().size() >= 2, "Should find at least 2 materials with 'Special'");
|
||||||
|
|
||||||
|
for (Material m : result.toList()) {
|
||||||
|
boolean matches = m.getName().toUpperCase().contains("SPECIAL") ||
|
||||||
|
m.getPartNumber().toUpperCase().contains("SPECIAL");
|
||||||
|
assertTrue(matches, "Material should match filter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListMaterialsExcludeDeprecated() {
|
||||||
|
// Given: Insert deprecated and active materials
|
||||||
|
Material deprecated = createTestMaterial("DEPR-001", "Deprecated Material");
|
||||||
|
deprecated.setDeprecated(true);
|
||||||
|
materialRepository.insert(deprecated);
|
||||||
|
|
||||||
|
Material active = createTestMaterial("ACTIVE-001", "Active Material");
|
||||||
|
materialRepository.insert(active);
|
||||||
|
|
||||||
|
// When: List excluding deprecated
|
||||||
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
||||||
|
SearchQueryResult<Material> result = materialRepository.listMaterials(
|
||||||
|
Optional.empty(), true, pagination
|
||||||
|
);
|
||||||
|
|
||||||
|
// Then: Should not include deprecated materials
|
||||||
|
assertNotNull(result);
|
||||||
|
for (Material m : result.toList()) {
|
||||||
|
assertFalse(m.getDeprecated(), "Should not include deprecated materials");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListAllMaterials() {
|
||||||
|
// Given: Insert materials
|
||||||
|
Material material1 = createTestMaterial("ALL-001", "Material 1");
|
||||||
|
materialRepository.insert(material1);
|
||||||
|
|
||||||
|
Material material2 = createTestMaterial("ALL-002", "Material 2");
|
||||||
|
materialRepository.insert(material2);
|
||||||
|
|
||||||
|
// When: List all
|
||||||
|
List<Material> materials = materialRepository.listAllMaterials();
|
||||||
|
|
||||||
|
// Then: Should return all materials ordered by normalized_part_number
|
||||||
|
assertNotNull(materials);
|
||||||
|
assertFalse(materials.isEmpty());
|
||||||
|
|
||||||
|
// Verify ordering
|
||||||
|
for (int i = 1; i < materials.size(); i++) {
|
||||||
|
String prev = materials.get(i - 1).getNormalizedPartNumber();
|
||||||
|
String current = materials.get(i).getNormalizedPartNumber();
|
||||||
|
assertTrue(prev.compareTo(current) <= 0,
|
||||||
|
"Materials should be ordered by normalized_part_number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPartNumber() {
|
||||||
|
// Given: Insert material
|
||||||
|
Material material = createTestMaterial("BYPART-001", "Get By Part");
|
||||||
|
materialRepository.insert(material);
|
||||||
|
|
||||||
|
// When: Get by part number
|
||||||
|
Optional<Material> result = materialRepository.getByPartNumber("BYPART-001");
|
||||||
|
|
||||||
|
// Then: Should find material
|
||||||
|
assertTrue(result.isPresent());
|
||||||
|
assertEquals("BYPART-001", result.get().getPartNumber());
|
||||||
|
assertEquals("Get By Part", result.get().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPartNumberNotFound() {
|
||||||
|
// When: Get by non-existent part number
|
||||||
|
Optional<Material> result = materialRepository.getByPartNumber("NONEXISTENT-999");
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(result.isPresent(), "Should not find material with non-existent part number");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPartNumbers() {
|
||||||
|
// Given: Insert multiple materials
|
||||||
|
Material material1 = createTestMaterial("BULK-001", "Bulk Material 1");
|
||||||
|
materialRepository.insert(material1);
|
||||||
|
|
||||||
|
Material material2 = createTestMaterial("BULK-002", "Bulk Material 2");
|
||||||
|
materialRepository.insert(material2);
|
||||||
|
|
||||||
|
Material material3 = createTestMaterial("BULK-003", "Bulk Material 3");
|
||||||
|
materialRepository.insert(material3);
|
||||||
|
|
||||||
|
// When: Get by part numbers
|
||||||
|
List<String> partNumbers = List.of("BULK-001", "BULK-002", "NONEXISTENT");
|
||||||
|
List<Material> materials = materialRepository.getByPartNumbers(partNumbers);
|
||||||
|
|
||||||
|
// Then: Should find existing materials (2 out of 3 part numbers)
|
||||||
|
assertNotNull(materials);
|
||||||
|
assertTrue(materials.size() >= 2, "Should find at least 2 materials");
|
||||||
|
|
||||||
|
List<String> foundPartNumbers = materials.stream()
|
||||||
|
.map(Material::getPartNumber)
|
||||||
|
.toList();
|
||||||
|
assertTrue(foundPartNumbers.contains("BULK-001"));
|
||||||
|
assertTrue(foundPartNumbers.contains("BULK-002"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPartNumbersEmptyList() {
|
||||||
|
// When: Get by empty list
|
||||||
|
List<Material> materials = materialRepository.getByPartNumbers(List.of());
|
||||||
|
|
||||||
|
// Then: Should return empty list
|
||||||
|
assertNotNull(materials);
|
||||||
|
assertTrue(materials.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteByIds() {
|
||||||
|
// Given: Insert multiple materials
|
||||||
|
Material material1 = createTestMaterial("DELETE-001", "To Delete 1");
|
||||||
|
materialRepository.insert(material1);
|
||||||
|
Integer id1 = materialRepository.getByPartNumber("DELETE-001").orElseThrow().getId();
|
||||||
|
|
||||||
|
Material material2 = createTestMaterial("DELETE-002", "To Delete 2");
|
||||||
|
materialRepository.insert(material2);
|
||||||
|
Integer id2 = materialRepository.getByPartNumber("DELETE-002").orElseThrow().getId();
|
||||||
|
|
||||||
|
// When: Delete by IDs
|
||||||
|
materialRepository.deleteByIds(List.of(id1, id2));
|
||||||
|
|
||||||
|
// Then: Should be deprecated
|
||||||
|
assertFalse(materialRepository.getById(id1).isPresent());
|
||||||
|
assertFalse(materialRepository.getById(id2).isPresent());
|
||||||
|
|
||||||
|
// But should exist with deprecated flag
|
||||||
|
assertTrue(materialRepository.getByIdIncludeDeprecated(id1).orElseThrow().getDeprecated());
|
||||||
|
assertTrue(materialRepository.getByIdIncludeDeprecated(id2).orElseThrow().getDeprecated());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFindMissingIds() {
|
||||||
|
// Given: Insert some materials
|
||||||
|
Material material1 = createTestMaterial("MISSING-001", "Material 1");
|
||||||
|
materialRepository.insert(material1);
|
||||||
|
Integer existingId = materialRepository.getByPartNumber("MISSING-001").orElseThrow().getId();
|
||||||
|
|
||||||
|
// When: Check for missing IDs
|
||||||
|
List<Integer> idsToCheck = List.of(existingId, 99999, 99998);
|
||||||
|
List<Integer> missingIds = materialRepository.findMissingIds(idsToCheck);
|
||||||
|
|
||||||
|
// Then: Should return only non-existent IDs
|
||||||
|
assertNotNull(missingIds);
|
||||||
|
assertEquals(2, missingIds.size(), "Should find 2 missing IDs");
|
||||||
|
assertTrue(missingIds.contains(99999));
|
||||||
|
assertTrue(missingIds.contains(99998));
|
||||||
|
assertFalse(missingIds.contains(existingId), "Existing ID should not be in missing list");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFindMissingIdsEmptyList() {
|
||||||
|
// When: Check empty list
|
||||||
|
List<Integer> missingIds = materialRepository.findMissingIds(List.of());
|
||||||
|
|
||||||
|
// Then: Should return empty list
|
||||||
|
assertNotNull(missingIds);
|
||||||
|
assertTrue(missingIds.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private Material createTestMaterial(String partNumber, String name) {
|
||||||
|
Material material = new Material();
|
||||||
|
material.setPartNumber(partNumber);
|
||||||
|
material.setNormalizedPartNumber(partNumber.toUpperCase());
|
||||||
|
material.setName(name);
|
||||||
|
material.setHsCode(null);
|
||||||
|
material.setDeprecated(false);
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
package de.avatic.lcc.repositories;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for NomenclatureRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - Search with LIKE and CONCAT functions
|
||||||
|
* - Pagination (LIMIT/OFFSET vs OFFSET/FETCH)
|
||||||
|
* - ORDER BY compatibility
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=NomenclatureRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=NomenclatureRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class NomenclatureRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NomenclatureRepository nomenclatureRepository;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setupTestData() {
|
||||||
|
// Insert test HS codes into the nomenclature table
|
||||||
|
String sql = "INSERT INTO nomenclature (hs_code, description) VALUES (?, ?)";
|
||||||
|
|
||||||
|
executeRawSql(sql, "8471300000", "Portable automatic data processing machines, weighing not more than 10 kg");
|
||||||
|
executeRawSql(sql, "8471410000", "Comprising in the same housing at least a central processing unit");
|
||||||
|
executeRawSql(sql, "8471420000", "Other, presented in the form of systems");
|
||||||
|
executeRawSql(sql, "8471490000", "Other automatic data processing machines");
|
||||||
|
executeRawSql(sql, "8471500000", "Processing units other than those of subheading 8471.41 or 8471.49");
|
||||||
|
executeRawSql(sql, "8471600000", "Input or output units");
|
||||||
|
executeRawSql(sql, "8471700000", "Storage units");
|
||||||
|
executeRawSql(sql, "8471800000", "Other units of automatic data processing machines");
|
||||||
|
executeRawSql(sql, "9403200000", "Other metal furniture");
|
||||||
|
executeRawSql(sql, "9403300000", "Wooden furniture of a kind used in offices");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchHsCodeWithExactMatch() {
|
||||||
|
// Given: Search for exact HS code prefix
|
||||||
|
String search = "847130";
|
||||||
|
|
||||||
|
// When: Search
|
||||||
|
List<String> results = nomenclatureRepository.searchHsCode(search);
|
||||||
|
|
||||||
|
// Then: Should find matching HS codes starting with 847130
|
||||||
|
assertNotNull(results);
|
||||||
|
assertFalse(results.isEmpty(), "Should find HS codes starting with 847130");
|
||||||
|
assertTrue(results.stream().anyMatch(code -> code.startsWith("847130")),
|
||||||
|
"Results should contain codes starting with 847130");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchHsCodeWithPartialMatch() {
|
||||||
|
// Given: Search for partial HS code
|
||||||
|
String search = "8471";
|
||||||
|
|
||||||
|
// When: Search
|
||||||
|
List<String> results = nomenclatureRepository.searchHsCode(search);
|
||||||
|
|
||||||
|
// Then: Should find all HS codes starting with 8471
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.size() >= 7, "Should find at least 7 codes starting with 8471");
|
||||||
|
|
||||||
|
// Verify all results start with the search term
|
||||||
|
for (String code : results) {
|
||||||
|
assertTrue(code.startsWith(search),
|
||||||
|
"All results should start with search term: " + code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchHsCodeOrdering() {
|
||||||
|
// Given: Search for codes
|
||||||
|
String search = "8471";
|
||||||
|
|
||||||
|
// When: Search
|
||||||
|
List<String> results = nomenclatureRepository.searchHsCode(search);
|
||||||
|
|
||||||
|
// Then: Should be ordered by hs_code
|
||||||
|
assertNotNull(results);
|
||||||
|
assertFalse(results.isEmpty());
|
||||||
|
|
||||||
|
// Verify ordering
|
||||||
|
for (int i = 1; i < results.size(); i++) {
|
||||||
|
assertTrue(results.get(i - 1).compareTo(results.get(i)) <= 0,
|
||||||
|
"Results should be ordered by hs_code");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchHsCodeWithPagination() {
|
||||||
|
// Given: Search that returns many results
|
||||||
|
String search = "8471";
|
||||||
|
|
||||||
|
// When: Search (limit is 10 as per repository implementation)
|
||||||
|
List<String> results = nomenclatureRepository.searchHsCode(search);
|
||||||
|
|
||||||
|
// Then: Should respect pagination limit
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.size() <= 10, "Should return at most 10 results (pagination limit)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchHsCodeNotFound() {
|
||||||
|
// Given: Search for non-existent HS code
|
||||||
|
String search = "9999";
|
||||||
|
|
||||||
|
// When: Search
|
||||||
|
List<String> results = nomenclatureRepository.searchHsCode(search);
|
||||||
|
|
||||||
|
// Then: Should return empty list
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.isEmpty(), "Should return empty list for non-existent HS code");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchHsCodeDifferentPrefix() {
|
||||||
|
// Given: Search for different category (furniture)
|
||||||
|
String search = "9403";
|
||||||
|
|
||||||
|
// When: Search
|
||||||
|
List<String> results = nomenclatureRepository.searchHsCode(search);
|
||||||
|
|
||||||
|
// Then: Should find furniture codes
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.size() >= 2, "Should find at least 2 codes starting with 9403");
|
||||||
|
assertTrue(results.stream().allMatch(code -> code.startsWith("9403")),
|
||||||
|
"All results should start with 9403");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchHsCodeConcatFunction() {
|
||||||
|
// This test verifies that the CONCAT function works across both databases
|
||||||
|
// MySQL: CONCAT(?, '%')
|
||||||
|
// MSSQL: ? + '%'
|
||||||
|
|
||||||
|
// Given: Search with single digit
|
||||||
|
String search = "8";
|
||||||
|
|
||||||
|
// When: Search
|
||||||
|
List<String> results = nomenclatureRepository.searchHsCode(search);
|
||||||
|
|
||||||
|
// Then: Should find all codes starting with 8
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.size() >= 7, "Should find at least 7 codes starting with 8");
|
||||||
|
assertTrue(results.stream().allMatch(code -> code.startsWith("8")),
|
||||||
|
"All results should start with 8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
package de.avatic.lcc.repositories;
|
||||||
|
|
||||||
|
import de.avatic.lcc.model.db.packaging.PackagingDimension;
|
||||||
|
import de.avatic.lcc.model.db.packaging.PackagingType;
|
||||||
|
import de.avatic.lcc.model.db.utils.DimensionUnit;
|
||||||
|
import de.avatic.lcc.model.db.utils.WeightUnit;
|
||||||
|
import de.avatic.lcc.repositories.packaging.PackagingDimensionRepository;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for PackagingDimensionRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - CRUD operations
|
||||||
|
* - Boolean literal compatibility (deprecated filtering)
|
||||||
|
* - Enum handling (PackagingType, DimensionUnit, WeightUnit)
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=PackagingDimensionRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=PackagingDimensionRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class PackagingDimensionRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PackagingDimensionRepository packagingDimensionRepository;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsertAndRetrieve() {
|
||||||
|
// Given: Create packaging dimension
|
||||||
|
PackagingDimension dimension = createTestDimension(1000, 500, 300, 10000, 1);
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Optional<Integer> dimensionId = packagingDimensionRepository.insert(dimension);
|
||||||
|
|
||||||
|
// Then: Should be inserted successfully
|
||||||
|
assertTrue(dimensionId.isPresent(), "Dimension ID should be present");
|
||||||
|
assertTrue(dimensionId.get() > 0, "Dimension ID should be positive");
|
||||||
|
|
||||||
|
// When: Retrieve by ID
|
||||||
|
Optional<PackagingDimension> retrieved = packagingDimensionRepository.getById(dimensionId.get());
|
||||||
|
|
||||||
|
// Then: Should retrieve successfully
|
||||||
|
assertTrue(retrieved.isPresent(), "Dimension should be retrievable after insert");
|
||||||
|
assertEquals(1000, retrieved.get().getLength());
|
||||||
|
assertEquals(500, retrieved.get().getWidth());
|
||||||
|
assertEquals(300, retrieved.get().getHeight());
|
||||||
|
assertEquals(10000, retrieved.get().getWeight());
|
||||||
|
assertEquals(1, retrieved.get().getContentUnitCount());
|
||||||
|
assertEquals(PackagingType.HU, retrieved.get().getType());
|
||||||
|
assertEquals(DimensionUnit.CM, retrieved.get().getDimensionUnit());
|
||||||
|
assertEquals(WeightUnit.KG, retrieved.get().getWeightUnit());
|
||||||
|
assertFalse(retrieved.get().getDeprecated());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdate() {
|
||||||
|
// Given: Insert dimension
|
||||||
|
PackagingDimension dimension = createTestDimension(1000, 500, 300, 10000, 1);
|
||||||
|
Integer dimensionId = packagingDimensionRepository.insert(dimension).orElseThrow();
|
||||||
|
|
||||||
|
// When: Update dimension
|
||||||
|
PackagingDimension toUpdate = packagingDimensionRepository.getById(dimensionId).orElseThrow();
|
||||||
|
toUpdate.setLength(1200);
|
||||||
|
toUpdate.setWidth(600);
|
||||||
|
toUpdate.setHeight(400);
|
||||||
|
toUpdate.setWeight(15000);
|
||||||
|
toUpdate.setContentUnitCount(2);
|
||||||
|
packagingDimensionRepository.update(toUpdate);
|
||||||
|
|
||||||
|
// Then: Verify update
|
||||||
|
PackagingDimension updated = packagingDimensionRepository.getById(dimensionId).orElseThrow();
|
||||||
|
assertEquals(1200, updated.getLength());
|
||||||
|
assertEquals(600, updated.getWidth());
|
||||||
|
assertEquals(400, updated.getHeight());
|
||||||
|
assertEquals(15000, updated.getWeight());
|
||||||
|
assertEquals(2, updated.getContentUnitCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSetDeprecatedById() {
|
||||||
|
// Given: Insert dimension
|
||||||
|
PackagingDimension dimension = createTestDimension(1000, 500, 300, 10000, 1);
|
||||||
|
Integer dimensionId = packagingDimensionRepository.insert(dimension).orElseThrow();
|
||||||
|
|
||||||
|
// When: Deprecate
|
||||||
|
Optional<Integer> result = packagingDimensionRepository.setDeprecatedById(dimensionId);
|
||||||
|
|
||||||
|
// Then: Should be deprecated
|
||||||
|
assertTrue(result.isPresent());
|
||||||
|
|
||||||
|
// getById() excludes deprecated dimensions
|
||||||
|
Optional<PackagingDimension> deprecated = packagingDimensionRepository.getById(dimensionId);
|
||||||
|
assertFalse(deprecated.isPresent(), "Deprecated dimension should not be retrievable via getById()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByIdNotFound() {
|
||||||
|
// When: Get by non-existent ID
|
||||||
|
Optional<PackagingDimension> result = packagingDimensionRepository.getById(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(result.isPresent(), "Should not find dimension with non-existent ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDifferentPackagingTypes() {
|
||||||
|
// Given: Insert dimensions with different types
|
||||||
|
PackagingDimension hu = createTestDimension(1000, 500, 300, 10000, 1);
|
||||||
|
hu.setType(PackagingType.HU);
|
||||||
|
Integer huId = packagingDimensionRepository.insert(hu).orElseThrow();
|
||||||
|
|
||||||
|
PackagingDimension shu = createTestDimension(500, 300, 200, 5000, 1);
|
||||||
|
shu.setType(PackagingType.SHU);
|
||||||
|
Integer shuId = packagingDimensionRepository.insert(shu).orElseThrow();
|
||||||
|
|
||||||
|
// When: Retrieve both
|
||||||
|
PackagingDimension retrievedHu = packagingDimensionRepository.getById(huId).orElseThrow();
|
||||||
|
PackagingDimension retrievedShu = packagingDimensionRepository.getById(shuId).orElseThrow();
|
||||||
|
|
||||||
|
// Then: Should have correct types
|
||||||
|
assertEquals(PackagingType.HU, retrievedHu.getType());
|
||||||
|
assertEquals(PackagingType.SHU, retrievedShu.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDifferentUnits() {
|
||||||
|
// Given: Insert dimension with different units (meters and grams instead of cm and kg)
|
||||||
|
PackagingDimension dimension = createTestDimension(1, 1, 1, 1000, 1); // meters and grams
|
||||||
|
dimension.setDimensionUnit(DimensionUnit.M);
|
||||||
|
dimension.setWeightUnit(WeightUnit.G);
|
||||||
|
Integer dimensionId = packagingDimensionRepository.insert(dimension).orElseThrow();
|
||||||
|
|
||||||
|
// When: Retrieve
|
||||||
|
PackagingDimension retrieved = packagingDimensionRepository.getById(dimensionId).orElseThrow();
|
||||||
|
|
||||||
|
// Then: Should have correct units
|
||||||
|
assertEquals(DimensionUnit.M, retrieved.getDimensionUnit());
|
||||||
|
assertEquals(WeightUnit.G, retrieved.getWeightUnit());
|
||||||
|
assertEquals(1, retrieved.getLength());
|
||||||
|
assertEquals(1, retrieved.getWidth());
|
||||||
|
assertEquals(1, retrieved.getHeight());
|
||||||
|
assertEquals(1000, retrieved.getWeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateWithDeprecation() {
|
||||||
|
// Given: Insert dimension
|
||||||
|
PackagingDimension dimension = createTestDimension(1000, 500, 300, 10000, 1);
|
||||||
|
Integer dimensionId = packagingDimensionRepository.insert(dimension).orElseThrow();
|
||||||
|
|
||||||
|
// When: Update and deprecate
|
||||||
|
PackagingDimension toUpdate = packagingDimensionRepository.getById(dimensionId).orElseThrow();
|
||||||
|
toUpdate.setDeprecated(true);
|
||||||
|
packagingDimensionRepository.update(toUpdate);
|
||||||
|
|
||||||
|
// Then: Should not be retrievable via getById() (which filters deprecated)
|
||||||
|
Optional<PackagingDimension> deprecated = packagingDimensionRepository.getById(dimensionId);
|
||||||
|
assertFalse(deprecated.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private PackagingDimension createTestDimension(Integer length, Integer width, Integer height, Integer weight, Integer contentUnitCount) {
|
||||||
|
PackagingDimension dimension = new PackagingDimension();
|
||||||
|
dimension.setType(PackagingType.HU);
|
||||||
|
dimension.setLength(length);
|
||||||
|
dimension.setWidth(width);
|
||||||
|
dimension.setHeight(height);
|
||||||
|
dimension.setDimensionUnit(DimensionUnit.CM);
|
||||||
|
dimension.setWeight(weight);
|
||||||
|
dimension.setWeightUnit(WeightUnit.KG);
|
||||||
|
dimension.setContentUnitCount(contentUnitCount);
|
||||||
|
dimension.setDeprecated(false);
|
||||||
|
return dimension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,9 +37,16 @@ class PackagingRepositoryIntegrationTest extends AbstractRepositoryIntegrationTe
|
||||||
private Integer testMaterialId2;
|
private Integer testMaterialId2;
|
||||||
private Integer testNodeId1;
|
private Integer testNodeId1;
|
||||||
private Integer testNodeId2;
|
private Integer testNodeId2;
|
||||||
|
private Integer testDimensionId1;
|
||||||
|
private Integer testDimensionId2;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setupTestData() {
|
void setupTestData() {
|
||||||
|
// Create test packaging dimensions (required by foreign key)
|
||||||
|
// Dimensions: length, width, height in mm, weight in g, content_unit_count
|
||||||
|
testDimensionId1 = createTestDimension(1000, 500, 300, 10000, 1);
|
||||||
|
testDimensionId2 = createTestDimension(1200, 600, 400, 15000, 1);
|
||||||
|
|
||||||
// Create test materials (required by foreign key)
|
// Create test materials (required by foreign key)
|
||||||
testMaterialId1 = createTestMaterial("TEST-MAT-001", "Test Material 1");
|
testMaterialId1 = createTestMaterial("TEST-MAT-001", "Test Material 1");
|
||||||
testMaterialId2 = createTestMaterial("TEST-MAT-002", "Test Material 2");
|
testMaterialId2 = createTestMaterial("TEST-MAT-002", "Test Material 2");
|
||||||
|
|
@ -55,8 +62,8 @@ class PackagingRepositoryIntegrationTest extends AbstractRepositoryIntegrationTe
|
||||||
Packaging packaging = new Packaging();
|
Packaging packaging = new Packaging();
|
||||||
packaging.setMaterialId(testMaterialId1);
|
packaging.setMaterialId(testMaterialId1);
|
||||||
packaging.setSupplierId(testNodeId1);
|
packaging.setSupplierId(testNodeId1);
|
||||||
packaging.setHuId(1); // Handling unit dimension
|
packaging.setHuId(testDimensionId1); // Handling unit dimension
|
||||||
packaging.setShuId(1); // Shipping handling unit dimension
|
packaging.setShuId(testDimensionId1); // Shipping handling unit dimension
|
||||||
packaging.setDeprecated(false);
|
packaging.setDeprecated(false);
|
||||||
|
|
||||||
// When: Insert
|
// When: Insert
|
||||||
|
|
@ -81,25 +88,25 @@ class PackagingRepositoryIntegrationTest extends AbstractRepositoryIntegrationTe
|
||||||
@Test
|
@Test
|
||||||
void testUpdate() {
|
void testUpdate() {
|
||||||
// Given: Create and insert packaging
|
// Given: Create and insert packaging
|
||||||
Packaging packaging = createTestPackaging(testMaterialId1, testNodeId1, 1, 1, false);
|
Packaging packaging = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
Integer packagingId = packagingRepository.insert(packaging).orElseThrow();
|
Integer packagingId = packagingRepository.insert(packaging).orElseThrow();
|
||||||
|
|
||||||
// When: Update packaging
|
// When: Update packaging
|
||||||
Packaging toUpdate = packagingRepository.getById(packagingId).orElseThrow();
|
Packaging toUpdate = packagingRepository.getById(packagingId).orElseThrow();
|
||||||
toUpdate.setHuId(2);
|
toUpdate.setHuId(testDimensionId2);
|
||||||
toUpdate.setShuId(2);
|
toUpdate.setShuId(testDimensionId2);
|
||||||
packagingRepository.update(toUpdate);
|
packagingRepository.update(toUpdate);
|
||||||
|
|
||||||
// Then: Verify update
|
// Then: Verify update
|
||||||
Packaging updated = packagingRepository.getById(packagingId).orElseThrow();
|
Packaging updated = packagingRepository.getById(packagingId).orElseThrow();
|
||||||
assertEquals(2, updated.getHuId());
|
assertEquals(testDimensionId2, updated.getHuId());
|
||||||
assertEquals(2, updated.getShuId());
|
assertEquals(testDimensionId2, updated.getShuId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSetDeprecatedById() {
|
void testSetDeprecatedById() {
|
||||||
// Given: Create packaging
|
// Given: Create packaging
|
||||||
Packaging packaging = createTestPackaging(1, 1, 1, 1, false);
|
Packaging packaging = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
Integer packagingId = packagingRepository.insert(packaging).orElseThrow();
|
Integer packagingId = packagingRepository.insert(packaging).orElseThrow();
|
||||||
|
|
||||||
// When: Deprecate
|
// When: Deprecate
|
||||||
|
|
@ -115,7 +122,7 @@ class PackagingRepositoryIntegrationTest extends AbstractRepositoryIntegrationTe
|
||||||
void testListPackagingWithPagination() {
|
void testListPackagingWithPagination() {
|
||||||
// Given: Create multiple packagings
|
// Given: Create multiple packagings
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
Packaging packaging = createTestPackaging(1, 1, 1, 1, false);
|
Packaging packaging = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging);
|
packagingRepository.insert(packaging);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,54 +141,54 @@ class PackagingRepositoryIntegrationTest extends AbstractRepositoryIntegrationTe
|
||||||
@Test
|
@Test
|
||||||
void testListPackagingFilterByMaterialId() {
|
void testListPackagingFilterByMaterialId() {
|
||||||
// Given: Create packagings with different materials
|
// Given: Create packagings with different materials
|
||||||
Packaging packaging1 = createTestPackaging(1, 1, 1, 1, false);
|
Packaging packaging1 = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging1);
|
packagingRepository.insert(packaging1);
|
||||||
|
|
||||||
Packaging packaging2 = createTestPackaging(2, 1, 1, 1, false);
|
Packaging packaging2 = createTestPackaging(testMaterialId2, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging2);
|
packagingRepository.insert(packaging2);
|
||||||
|
|
||||||
// When: Filter by materialId=1
|
// When: Filter by materialId
|
||||||
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
||||||
SearchQueryResult<Packaging> result = packagingRepository.listPackaging(
|
SearchQueryResult<Packaging> result = packagingRepository.listPackaging(
|
||||||
1, null, false, pagination
|
testMaterialId1, null, false, pagination
|
||||||
);
|
);
|
||||||
|
|
||||||
// Then: Should only return material 1 packagings
|
// Then: Should only return material 1 packagings
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
for (Packaging p : result.toList()) {
|
for (Packaging p : result.toList()) {
|
||||||
assertEquals(1, p.getMaterialId(), "Should only return packagings with materialId=1");
|
assertEquals(testMaterialId1, p.getMaterialId(), "Should only return packagings with correct materialId");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testListPackagingFilterBySupplierId() {
|
void testListPackagingFilterBySupplierId() {
|
||||||
// Given: Create packagings with different suppliers
|
// Given: Create packagings with different suppliers
|
||||||
Packaging packaging1 = createTestPackaging(1, 1, 1, 1, false);
|
Packaging packaging1 = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging1);
|
packagingRepository.insert(packaging1);
|
||||||
|
|
||||||
Packaging packaging2 = createTestPackaging(1, 2, 1, 1, false);
|
Packaging packaging2 = createTestPackaging(testMaterialId1, testNodeId2, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging2);
|
packagingRepository.insert(packaging2);
|
||||||
|
|
||||||
// When: Filter by supplierId=1
|
// When: Filter by supplierId
|
||||||
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
||||||
SearchQueryResult<Packaging> result = packagingRepository.listPackaging(
|
SearchQueryResult<Packaging> result = packagingRepository.listPackaging(
|
||||||
null, 1, false, pagination
|
null, testNodeId1, false, pagination
|
||||||
);
|
);
|
||||||
|
|
||||||
// Then: Should only return supplier 1 packagings
|
// Then: Should only return supplier 1 packagings
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
for (Packaging p : result.toList()) {
|
for (Packaging p : result.toList()) {
|
||||||
assertEquals(1, p.getSupplierId(), "Should only return packagings with supplierId=1");
|
assertEquals(testNodeId1, p.getSupplierId(), "Should only return packagings with correct supplierId");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testListPackagingExcludeDeprecated() {
|
void testListPackagingExcludeDeprecated() {
|
||||||
// Given: Create deprecated and non-deprecated packagings
|
// Given: Create deprecated and non-deprecated packagings
|
||||||
Packaging deprecated = createTestPackaging(1, 1, 1, 1, true);
|
Packaging deprecated = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, true);
|
||||||
packagingRepository.insert(deprecated);
|
packagingRepository.insert(deprecated);
|
||||||
|
|
||||||
Packaging active = createTestPackaging(1, 1, 1, 1, false);
|
Packaging active = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(active);
|
packagingRepository.insert(active);
|
||||||
|
|
||||||
// When: List excluding deprecated
|
// When: List excluding deprecated
|
||||||
|
|
@ -200,37 +207,37 @@ class PackagingRepositoryIntegrationTest extends AbstractRepositoryIntegrationTe
|
||||||
@Test
|
@Test
|
||||||
void testGetByMaterialId() {
|
void testGetByMaterialId() {
|
||||||
// Given: Create packagings for specific material
|
// Given: Create packagings for specific material
|
||||||
Packaging packaging1 = createTestPackaging(10, 1, 1, 1, false);
|
Packaging packaging1 = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging1);
|
packagingRepository.insert(packaging1);
|
||||||
|
|
||||||
Packaging packaging2 = createTestPackaging(10, 2, 1, 1, false);
|
Packaging packaging2 = createTestPackaging(testMaterialId1, testNodeId2, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging2);
|
packagingRepository.insert(packaging2);
|
||||||
|
|
||||||
// When: Get by materialId
|
// When: Get by materialId
|
||||||
List<Packaging> packagings = packagingRepository.getByMaterialId(10);
|
List<Packaging> packagings = packagingRepository.getByMaterialId(testMaterialId1);
|
||||||
|
|
||||||
// Then: Should return all packagings for that material
|
// Then: Should return all packagings for that material
|
||||||
assertNotNull(packagings);
|
assertNotNull(packagings);
|
||||||
assertTrue(packagings.size() >= 2, "Should find at least 2 packagings for material 10");
|
assertTrue(packagings.size() >= 2, "Should find at least 2 packagings for material");
|
||||||
for (Packaging p : packagings) {
|
for (Packaging p : packagings) {
|
||||||
assertEquals(10, p.getMaterialId());
|
assertEquals(testMaterialId1, p.getMaterialId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetByMaterialIdAndSupplierId() {
|
void testGetByMaterialIdAndSupplierId() {
|
||||||
// Given: Create packaging with specific material and supplier
|
// Given: Create packaging with specific material and supplier
|
||||||
Packaging packaging = createTestPackaging(15, 15, 1, 1, false);
|
Packaging packaging = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
Integer packagingId = packagingRepository.insert(packaging).orElseThrow();
|
Integer packagingId = packagingRepository.insert(packaging).orElseThrow();
|
||||||
|
|
||||||
// When: Get by materialId and supplierId
|
// When: Get by materialId and supplierId
|
||||||
Optional<Packaging> result = packagingRepository.getByMaterialIdAndSupplierId(15, 15);
|
Optional<Packaging> result = packagingRepository.getByMaterialIdAndSupplierId(testMaterialId1, testNodeId1);
|
||||||
|
|
||||||
// Then: Should find the packaging
|
// Then: Should find the packaging
|
||||||
assertTrue(result.isPresent(), "Should find packaging with materialId=15 and supplierId=15");
|
assertTrue(result.isPresent(), "Should find packaging with correct IDs");
|
||||||
assertEquals(packagingId, result.get().getId());
|
assertEquals(packagingId, result.get().getId());
|
||||||
assertEquals(15, result.get().getMaterialId());
|
assertEquals(testMaterialId1, result.get().getMaterialId());
|
||||||
assertEquals(15, result.get().getSupplierId());
|
assertEquals(testNodeId1, result.get().getSupplierId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -245,10 +252,10 @@ class PackagingRepositoryIntegrationTest extends AbstractRepositoryIntegrationTe
|
||||||
@Test
|
@Test
|
||||||
void testListAllPackaging() {
|
void testListAllPackaging() {
|
||||||
// Given: Create packagings
|
// Given: Create packagings
|
||||||
Packaging packaging1 = createTestPackaging(1, 1, 1, 1, false);
|
Packaging packaging1 = createTestPackaging(testMaterialId1, testNodeId1, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging1);
|
packagingRepository.insert(packaging1);
|
||||||
|
|
||||||
Packaging packaging2 = createTestPackaging(2, 2, 1, 1, false);
|
Packaging packaging2 = createTestPackaging(testMaterialId2, testNodeId2, testDimensionId1, testDimensionId1, false);
|
||||||
packagingRepository.insert(packaging2);
|
packagingRepository.insert(packaging2);
|
||||||
|
|
||||||
// When: List all
|
// When: List all
|
||||||
|
|
@ -267,6 +274,37 @@ class PackagingRepositoryIntegrationTest extends AbstractRepositoryIntegrationTe
|
||||||
|
|
||||||
// ========== Helper Methods ==========
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private Integer createTestDimension(Integer length, Integer width, Integer height, Integer weight, Integer contentUnitCount) {
|
||||||
|
String sql = "INSERT INTO packaging_dimension (length, width, height, weight, content_unit_count) VALUES (?, ?, ?, ?, ?)";
|
||||||
|
executeRawSql(sql, length, width, height, weight, contentUnitCount);
|
||||||
|
|
||||||
|
// Get last inserted ID
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createTestMaterial(String partNumber, String name) {
|
||||||
|
String sql = "INSERT INTO material (part_number, normalized_part_number, name, is_deprecated) VALUES (?, ?, ?, " +
|
||||||
|
dialectProvider.getBooleanFalse() + ")";
|
||||||
|
executeRawSql(sql, partNumber, partNumber.toUpperCase(), name);
|
||||||
|
|
||||||
|
// Get last inserted ID (works for both MySQL and MSSQL after ServiceConnection auto-config)
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createTestNode(String name, Integer countryId) {
|
||||||
|
String sql = "INSERT INTO node (name, address, geo_lat, geo_lng, is_deprecated, is_destination, is_source, is_intermediate, country_id, predecessor_required) " +
|
||||||
|
"VALUES (?, ?, ?, ?, " + dialectProvider.getBooleanFalse() + ", " +
|
||||||
|
dialectProvider.getBooleanTrue() + ", " + dialectProvider.getBooleanTrue() + ", " +
|
||||||
|
dialectProvider.getBooleanFalse() + ", ?, " + dialectProvider.getBooleanFalse() + ")";
|
||||||
|
executeRawSql(sql, name, "Test Address", 50.0, 10.0, countryId);
|
||||||
|
|
||||||
|
// Get last inserted ID
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
private Packaging createTestPackaging(Integer materialId, Integer supplierId, Integer huId, Integer shuId, boolean deprecated) {
|
private Packaging createTestPackaging(Integer materialId, Integer supplierId, Integer huId, Integer shuId, boolean deprecated) {
|
||||||
Packaging packaging = new Packaging();
|
Packaging packaging = new Packaging();
|
||||||
packaging.setMaterialId(materialId);
|
packaging.setMaterialId(materialId);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,284 @@
|
||||||
|
package de.avatic.lcc.repositories.users;
|
||||||
|
|
||||||
|
import de.avatic.lcc.model.db.nodes.Node;
|
||||||
|
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.math.BigDecimal;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for UserNodeRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - CRUD operations (Create, Read)
|
||||||
|
* - Search with filtering and pagination
|
||||||
|
* - Boolean literal compatibility (is_deprecated filtering)
|
||||||
|
* - Bulk operations (getByIds, checkOwner)
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=UserNodeRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=UserNodeRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class UserNodeRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserNodeRepository userNodeRepository;
|
||||||
|
|
||||||
|
private Integer testUserId1;
|
||||||
|
private Integer testUserId2;
|
||||||
|
private Integer testCountryId;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setupTestData() {
|
||||||
|
// Create test users
|
||||||
|
testUserId1 = createTestUser("user1@test.com", "WORKDAY001");
|
||||||
|
testUserId2 = createTestUser("user2@test.com", "WORKDAY002");
|
||||||
|
|
||||||
|
// Use existing country (id=1 should exist from Flyway migrations)
|
||||||
|
testCountryId = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAddAndRetrieve() {
|
||||||
|
// Given: Create user node
|
||||||
|
Node node = createTestNode("Test Supplier Berlin", "Berlin, Germany", 52.5200, 13.4050);
|
||||||
|
|
||||||
|
// When: Add
|
||||||
|
Integer nodeId = userNodeRepository.add(testUserId1, node);
|
||||||
|
|
||||||
|
// Then: Should be inserted successfully
|
||||||
|
assertNotNull(nodeId);
|
||||||
|
assertTrue(nodeId > 0);
|
||||||
|
|
||||||
|
// When: Retrieve by ID
|
||||||
|
Optional<Node> retrieved = userNodeRepository.getById(nodeId);
|
||||||
|
|
||||||
|
// Then: Should retrieve successfully
|
||||||
|
assertTrue(retrieved.isPresent(), "User node should be retrievable after insert");
|
||||||
|
assertEquals("Test Supplier Berlin", retrieved.get().getName());
|
||||||
|
assertEquals("Berlin, Germany", retrieved.get().getAddress());
|
||||||
|
assertEquals(new BigDecimal("52.5200"), retrieved.get().getGeoLat());
|
||||||
|
assertEquals(new BigDecimal("13.4050"), retrieved.get().getGeoLng());
|
||||||
|
assertFalse(retrieved.get().getDeprecated());
|
||||||
|
assertEquals(testCountryId, retrieved.get().getCountryId());
|
||||||
|
assertTrue(retrieved.get().isUserNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByIdNotFound() {
|
||||||
|
// When: Get by non-existent ID
|
||||||
|
Optional<Node> result = userNodeRepository.getById(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(result.isPresent(), "Should not find user node with non-existent ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchNodeWithFilter() {
|
||||||
|
// Given: Insert multiple user nodes
|
||||||
|
Node node1 = createTestNode("Berlin Supplier", "Berlin", 52.5200, 13.4050);
|
||||||
|
userNodeRepository.add(testUserId1, node1);
|
||||||
|
|
||||||
|
Node node2 = createTestNode("Munich Supplier", "Munich", 48.1351, 11.5820);
|
||||||
|
userNodeRepository.add(testUserId1, node2);
|
||||||
|
|
||||||
|
Node node3 = createTestNode("Hamburg Distribution", "Hamburg", 53.5511, 9.9937);
|
||||||
|
userNodeRepository.add(testUserId1, node3);
|
||||||
|
|
||||||
|
// When: Search for "Supplier"
|
||||||
|
Collection<Node> results = userNodeRepository.searchNode("Supplier", 10, testUserId1, false);
|
||||||
|
|
||||||
|
// Then: Should find nodes with "Supplier" in name
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.size() >= 2, "Should find at least 2 nodes with 'Supplier'");
|
||||||
|
|
||||||
|
for (Node node : results) {
|
||||||
|
assertTrue(node.getName().contains("Supplier") || node.getAddress().contains("Supplier"),
|
||||||
|
"Results should match filter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchNodeWithPagination() {
|
||||||
|
// Given: Insert multiple user nodes
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
Node node = createTestNode("Supplier " + i, "Address " + i, 50.0 + i, 10.0 + i);
|
||||||
|
userNodeRepository.add(testUserId1, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When: Search with limit 3
|
||||||
|
Collection<Node> results = userNodeRepository.searchNode(null, 3, testUserId1, false);
|
||||||
|
|
||||||
|
// Then: Should respect pagination limit
|
||||||
|
assertNotNull(results);
|
||||||
|
assertTrue(results.size() <= 3, "Should return at most 3 nodes");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchNodeExcludeDeprecated() {
|
||||||
|
// Given: Insert deprecated and non-deprecated user nodes
|
||||||
|
Node deprecated = createTestNode("Deprecated Supplier", "Old Address", 50.0, 10.0);
|
||||||
|
deprecated.setDeprecated(true);
|
||||||
|
userNodeRepository.add(testUserId1, deprecated);
|
||||||
|
|
||||||
|
Node active = createTestNode("Active Supplier", "New Address", 51.0, 11.0);
|
||||||
|
userNodeRepository.add(testUserId1, active);
|
||||||
|
|
||||||
|
// When: Search excluding deprecated
|
||||||
|
Collection<Node> results = userNodeRepository.searchNode(null, 10, testUserId1, true);
|
||||||
|
|
||||||
|
// Then: Should not include deprecated nodes
|
||||||
|
assertNotNull(results);
|
||||||
|
for (Node node : results) {
|
||||||
|
assertFalse(node.getDeprecated(), "Should not include deprecated nodes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSearchNodeByUserId() {
|
||||||
|
// Given: Insert nodes for different users
|
||||||
|
Node user1Node = createTestNode("User 1 Supplier", "User 1 Address", 50.0, 10.0);
|
||||||
|
userNodeRepository.add(testUserId1, user1Node);
|
||||||
|
|
||||||
|
Node user2Node = createTestNode("User 2 Supplier", "User 2 Address", 51.0, 11.0);
|
||||||
|
userNodeRepository.add(testUserId2, user2Node);
|
||||||
|
|
||||||
|
// When: Search for user1 nodes
|
||||||
|
Collection<Node> user1Results = userNodeRepository.searchNode(null, 10, testUserId1, false);
|
||||||
|
|
||||||
|
// Then: Should only return user1 nodes
|
||||||
|
assertNotNull(user1Results);
|
||||||
|
// Can't assert exact count because other tests might have created nodes
|
||||||
|
// Just verify all returned nodes belong to user1
|
||||||
|
for (Node node : user1Results) {
|
||||||
|
// Note: We can't directly verify userId in the Node object since it's not stored there
|
||||||
|
// The verification happens implicitly through the WHERE clause
|
||||||
|
assertNotNull(node.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByIds() {
|
||||||
|
// Given: Insert multiple user nodes
|
||||||
|
Node node1 = createTestNode("Bulk Node 1", "Address 1", 50.0, 10.0);
|
||||||
|
Integer id1 = userNodeRepository.add(testUserId1, node1);
|
||||||
|
|
||||||
|
Node node2 = createTestNode("Bulk Node 2", "Address 2", 51.0, 11.0);
|
||||||
|
Integer id2 = userNodeRepository.add(testUserId1, node2);
|
||||||
|
|
||||||
|
Node node3 = createTestNode("Bulk Node 3", "Address 3", 52.0, 12.0);
|
||||||
|
Integer id3 = userNodeRepository.add(testUserId1, node3);
|
||||||
|
|
||||||
|
// When: Get by IDs
|
||||||
|
List<Integer> ids = List.of(id1, id2, id3);
|
||||||
|
Collection<Node> nodes = userNodeRepository.getByIds(ids);
|
||||||
|
|
||||||
|
// Then: Should return all requested nodes
|
||||||
|
assertNotNull(nodes);
|
||||||
|
assertEquals(3, nodes.size(), "Should return exactly 3 nodes");
|
||||||
|
|
||||||
|
List<Integer> retrievedIds = nodes.stream().map(Node::getId).toList();
|
||||||
|
assertTrue(retrievedIds.contains(id1));
|
||||||
|
assertTrue(retrievedIds.contains(id2));
|
||||||
|
assertTrue(retrievedIds.contains(id3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByIdsEmptyList() {
|
||||||
|
// When: Get by empty list
|
||||||
|
Collection<Node> nodes = userNodeRepository.getByIds(List.of());
|
||||||
|
|
||||||
|
// Then: Should return empty collection
|
||||||
|
assertNotNull(nodes);
|
||||||
|
assertTrue(nodes.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetOwnerById() {
|
||||||
|
// Given: Insert user node
|
||||||
|
Node node = createTestNode("Owner Test Node", "Address", 50.0, 10.0);
|
||||||
|
Integer nodeId = userNodeRepository.add(testUserId1, node);
|
||||||
|
|
||||||
|
// When: Get owner
|
||||||
|
Optional<Integer> owner = userNodeRepository.getOwnerById(nodeId);
|
||||||
|
|
||||||
|
// Then: Should return correct user ID
|
||||||
|
assertTrue(owner.isPresent());
|
||||||
|
assertEquals(testUserId1, owner.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetOwnerByIdNotFound() {
|
||||||
|
// When: Get owner of non-existent node
|
||||||
|
Optional<Integer> owner = userNodeRepository.getOwnerById(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(owner.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerValid() {
|
||||||
|
// Given: Insert user nodes
|
||||||
|
Node node1 = createTestNode("Owner Check 1", "Address 1", 50.0, 10.0);
|
||||||
|
Integer id1 = userNodeRepository.add(testUserId1, node1);
|
||||||
|
|
||||||
|
Node node2 = createTestNode("Owner Check 2", "Address 2", 51.0, 11.0);
|
||||||
|
Integer id2 = userNodeRepository.add(testUserId1, node2);
|
||||||
|
|
||||||
|
// When/Then: Should not throw exception for valid owner
|
||||||
|
assertDoesNotThrow(() ->
|
||||||
|
userNodeRepository.checkOwner(List.of(id1, id2), testUserId1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerInvalid() {
|
||||||
|
// Given: Insert user node for user1
|
||||||
|
Node node = createTestNode("Owner Violation", "Address", 50.0, 10.0);
|
||||||
|
Integer nodeId = userNodeRepository.add(testUserId1, node);
|
||||||
|
|
||||||
|
// When/Then: Should throw exception when user2 tries to access user1's node
|
||||||
|
assertThrows(Exception.class, () ->
|
||||||
|
userNodeRepository.checkOwner(List.of(nodeId), testUserId2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerEmptyList() {
|
||||||
|
// When/Then: Should not throw exception for empty list
|
||||||
|
assertDoesNotThrow(() ->
|
||||||
|
userNodeRepository.checkOwner(List.of(), testUserId1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private Integer createTestUser(String email, String workdayId) {
|
||||||
|
String sql = "INSERT INTO sys_user (email, workday_id, firstname, lastname, is_active) VALUES (?, ?, ?, ?, " +
|
||||||
|
dialectProvider.getBooleanTrue() + ")";
|
||||||
|
executeRawSql(sql, email, workdayId, "Test", "User");
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node createTestNode(String name, String address, double geoLat, double geoLng) {
|
||||||
|
Node node = new Node();
|
||||||
|
node.setName(name);
|
||||||
|
node.setAddress(address);
|
||||||
|
node.setGeoLat(new BigDecimal(String.valueOf(geoLat)));
|
||||||
|
node.setGeoLng(new BigDecimal(String.valueOf(geoLng)));
|
||||||
|
node.setDeprecated(false);
|
||||||
|
node.setCountryId(testCountryId);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue