feat(product): Kernkomponenten implementiert, JavaDoc ergänzt und Unit-Tests hinzugefügt

pull/3/head
Lulia 2026-06-27 22:58:17 +02:00
parent 0b53d089bc
commit 6e5a6b5329
2 changed files with 31 additions and 20 deletions

View File

@ -1,15 +1 @@
[ {
"productId" : "P-0001",
"bezeichnung" : "M6 Schraube",
"einzelpreisNetto" : 1.00,
"mwstSatz" : "NORMAL",
"beschreibung" : "",
"kategorie" : ""
}, {
"productId" : "P-0002",
"bezeichnung" : "M8 SCHRAUBE",
"einzelpreisNetto" : 2.00,
"mwstSatz" : "NORMAL",
"beschreibung" : "",
"kategorie" : ""
} ]
[ ]

View File

@ -14,47 +14,72 @@ import de.hsmannheim.faktura.product.MwstSatz;
import de.hsmannheim.faktura.product.Product;
import de.hsmannheim.faktura.product.repository.ProductRepository;
/**
* Komponententest-Klasse für den ProductService (Gruppe G).
* Überprüft die Einhaltung der funktionalen Anforderungen und Geschäftsregeln
* aus dem Pflichtenheft vollständig ohne GUI-Abhängigkeiten (NF-TEST-02)[cite: 51, 379].
*/
public class ProductServiceTest {
private ProductService productService;
private ProductRepository productRepository;
/**
* Setzt vor jedem einzelnen Testlauf eine frische Testumgebung auf
* und bereinigt den lokalen JSON-Cache, um Seiteneffekte zu verhindern[cite: 16, 143].
*/
@BeforeEach
public void setUp() {
productRepository = new ProductRepository();
productService = new ProductService(productRepository);
// Cache leeren, damit alte JSON-Einträge die Tests nicht verfälschen
// Cache leeren, damit alte JSON-Einträge die Testergebnisse nicht verfälschen
for (Product p : productRepository.findAll()) {
productRepository.deleteById(p.getProductId());
}
}
/**
* Testet das erfolgreiche Anlegen eines validen Produkts mit allen Pflichtattributen.
* Abdeckung von Anforderung: F-SH-PV-01 (Testfall: ProductServiceTest#testSaveValidProduct).
*/
@Test
public void testSaveValidProduct() {
Product valid = new Product("P-0001", "M6 Schraube", new BigDecimal("10.50"), MwstSatz.NORMAL, "Beschreibung", "Werkzeug");
assertDoesNotThrow(() -> productService.saveProduct(valid));
assertTrue(productService.getProductById("P-0001").isPresent());
}
@Test
/**
* Prüft, ob Preise kleiner als 0.00 wie gefordert blockiert und mit einer Exception abgewiesen werden.
* Abdeckung von Anforderung: F-SH-PV-06 / AC-SH-PV-01 (Testfall: ProductServiceTest#testNegativePriceRejection)[cite: 142, 145, 159].
*/
@Test
public void testNegativePriceRejection() {
// AC-SH-PV-01: Preis kleiner als 0.00 muss abgelehnt werden
Product invalidProduct = new Product("P-9999", "Testprodukt", new BigDecimal("-1.00"), MwstSatz.NORMAL, "Test", "Test");
// Kompakt ohne Rumpf-Klammern löst die Warnung auf
assertThrows(IllegalArgumentException.class, () -> productService.saveProduct(invalidProduct));
assertThrows(IllegalArgumentException.class, () -> {
productService.saveProduct(invalidProduct);
});
}
/**
* Überprüft die Echtzeit-Filterung der Produktliste anhand einer Teilmenge des Namens,
* wobei Groß- und Kleinschreibung ignoriert werden muss.
* Abdeckung von Anforderung: F-SH-PV-05 / AC-SH-PV-03 (Testfall: ProductServiceTest#testSearchCaseInsensitive)[cite: 150, 153, 159].
*/
@Test
public void testSearchCaseInsensitive() {
// AC-SH-PV-03: Suchtest für Groß-/Kleinschreibung
Product p1 = new Product("P-0001", "M6 Schraube", new BigDecimal("1.00"), MwstSatz.NORMAL, "", "");
Product p2 = new Product("P-0002", "M8 SCHRAUBE", new BigDecimal("2.00"), MwstSatz.NORMAL, "", "");
productService.saveProduct(p1);
productService.saveProduct(p2);
// Suche nach "schraube" muss im Ergebnis exakt beide Objekte liefern
List<Product> results = productService.searchProducts("schraube");
assertEquals(2, results.size());
}