Fix mock tests

This commit is contained in:
Tour
2025-12-04 20:14:28 +01:00
parent 2ff6fcca17
commit ff8f5f2c1a
7 changed files with 408 additions and 366 deletions

View File

@@ -24,7 +24,7 @@ public class AuctionMonitorProducer {
@ConfigProperty(name = "auction.database.path") String dbPath) throws SQLException { @ConfigProperty(name = "auction.database.path") String dbPath) throws SQLException {
LOG.infof("Initializing DatabaseService with path: %s", dbPath); LOG.infof("Initializing DatabaseService with path: %s", dbPath);
DatabaseService db = new DatabaseService(dbPath); var db = new DatabaseService(dbPath);
db.ensureSchema(); db.ensureSchema();
return db; return db;
} }

View File

@@ -50,7 +50,7 @@ public class AuctionMonitorResource {
status.put("images", db.getImageCount()); status.put("images", db.getImageCount());
// Count closing soon // Count closing soon
int closingSoon = 0; var closingSoon = 0;
for (var lot : db.getAllLots()) { for (var lot : db.getAllLots()) {
if (lot.closingTime() != null && lot.minutesUntilClose() < 30) { if (lot.closingTime() != null && lot.minutesUntilClose() < 30) {
closingSoon++; closingSoon++;
@@ -86,8 +86,8 @@ public class AuctionMonitorResource {
stats.put("totalImages", db.getImageCount()); stats.put("totalImages", db.getImageCount());
// Lot statistics // Lot statistics
int activeLots = 0; var activeLots = 0;
int lotsWithBids = 0; var lotsWithBids = 0;
double totalBids = 0; double totalBids = 0;
for (var lot : lots) { for (var lot : lots) {
@@ -274,9 +274,9 @@ public class AuctionMonitorResource {
@Path("/test-notification") @Path("/test-notification")
public Response sendTestNotification(Map<String, String> request) { public Response sendTestNotification(Map<String, String> request) {
try { try {
String message = request.getOrDefault("message", "Test notification from Auction Monitor"); var message = request.getOrDefault("message", "Test notification from Auction Monitor");
String title = request.getOrDefault("title", "Test Notification"); var title = request.getOrDefault("title", "Test Notification");
int priority = Integer.parseInt(request.getOrDefault("priority", "0")); var priority = Integer.parseInt(request.getOrDefault("priority", "0"));
notifier.sendNotification(message, title, priority); notifier.sendNotification(message, title, priority);

View File

@@ -1,6 +1,10 @@
package auctiora; package auctiora;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.io.Console; import java.io.Console;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
@@ -75,6 +79,9 @@ public class DatabaseService {
FOREIGN KEY (lot_id) REFERENCES lots(lot_id) FOREIGN KEY (lot_id) REFERENCES lots(lot_id)
)"""); )""");
// Migrate existing tables to add missing columns
migrateSchema(stmt);
// Indexes for performance // Indexes for performance
stmt.execute("CREATE INDEX IF NOT EXISTS idx_auctions_country ON auctions(country)"); stmt.execute("CREATE INDEX IF NOT EXISTS idx_auctions_country ON auctions(country)");
stmt.execute("CREATE INDEX IF NOT EXISTS idx_lots_sale_id ON lots(sale_id)"); stmt.execute("CREATE INDEX IF NOT EXISTS idx_lots_sale_id ON lots(sale_id)");
@@ -82,6 +89,30 @@ public class DatabaseService {
} }
} }
/**
* Migrates existing database schema to add new columns.
* SQLite doesn't support DROP COLUMN, so we add columns with ALTER TABLE ADD COLUMN.
*/
private void migrateSchema(java.sql.Statement stmt) throws SQLException {
// Check if country column exists in auctions table
try (var rs = stmt.executeQuery("PRAGMA table_info(auctions)")) {
boolean hasCountry = false;
while (rs.next()) {
if ("country".equals(rs.getString("name"))) {
hasCountry = true;
break;
}
}
if (!hasCountry) {
log.info("Migrating schema: Adding 'country' column to auctions table");
stmt.execute("ALTER TABLE auctions ADD COLUMN country TEXT");
}
} catch (SQLException e) {
// Table might not exist yet, which is fine
log.debug("Could not check auctions table schema: " + e.getMessage());
}
}
/** /**
* Inserts or updates an auction record (typically called by external scraper) * Inserts or updates an auction record (typically called by external scraper)
*/ */
@@ -355,7 +386,7 @@ public class DatabaseService {
} }
} catch (SQLException e) { } catch (SQLException e) {
// Table might not exist in scraper format - that's ok // Table might not exist in scraper format - that's ok
IO.println(" Scraper auction table not found or incompatible schema"); log.info(" Scraper auction table not found or incompatible schema");
} }
return imported; return imported;

View File

@@ -1,5 +1,8 @@
package auctiora; package auctiora;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;

View File

@@ -1,5 +1,9 @@
package auctiora; package auctiora;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import javax.mail.*; import javax.mail.*;
import javax.mail.internet.*; import javax.mail.internet.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;

View File

@@ -1,5 +1,9 @@
package auctiora; package auctiora;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.core.Scalar; import org.opencv.core.Scalar;

View File

@@ -48,7 +48,7 @@ class IntegrationTest {
"non_existent.txt" "non_existent.txt"
); );
RateLimitedHttpClient httpClient = new RateLimitedHttpClient(); var httpClient = new RateLimitedHttpClient();
imageProcessor = new ImageProcessingService(db, detector, httpClient); imageProcessor = new ImageProcessingService(db, detector, httpClient);
monitor = new TroostwijkMonitor( monitor = new TroostwijkMonitor(
@@ -170,7 +170,7 @@ class IntegrationTest {
db.updateLotCurrentBid(updatedLot); db.updateLotCurrentBid(updatedLot);
// Send notification // Send notification
String message = String.format("Nieuw bod op kavel %d: €%.2f (was €%.2f)", var message = String.format("Nieuw bod op kavel %d: €%.2f (was €%.2f)",
lot.lotId(), 2000.00, 1500.00); lot.lotId(), 2000.00, 1500.00);
assertDoesNotThrow(() -> assertDoesNotThrow(() ->
@@ -212,7 +212,7 @@ class IntegrationTest {
assertTrue(closingSoon.minutesUntilClose() < 5); assertTrue(closingSoon.minutesUntilClose() < 5);
// Send high-priority notification // Send high-priority notification
String message = "Kavel " + closingSoon.lotId() + " sluit binnen 5 min."; var message = "Kavel " + closingSoon.lotId() + " sluit binnen 5 min.";
assertDoesNotThrow(() -> assertDoesNotThrow(() ->
notifier.sendNotification(message, "Lot nearing closure", 1) notifier.sendNotification(message, "Lot nearing closure", 1)
); );
@@ -281,7 +281,7 @@ class IntegrationTest {
assertDoesNotThrow(() -> monitor.processPendingImages()); assertDoesNotThrow(() -> monitor.processPendingImages());
// Verify database integrity // Verify database integrity
int imageCount = db.getImageCount(); var imageCount = db.getImageCount();
assertTrue(imageCount >= 0); assertTrue(imageCount >= 0);
} }
@@ -348,7 +348,7 @@ class IntegrationTest {
assertTrue(allLabels.contains("excavator") || allLabels.contains("machinery")); assertTrue(allLabels.contains("excavator") || allLabels.contains("machinery"));
// Simulate value estimation notification // Simulate value estimation notification
String message = String.format( var message = String.format(
"Lot contains: %s\nEstimated value: €%,.2f", "Lot contains: %s\nEstimated value: €%,.2f",
String.join(", ", allLabels), String.join(", ", allLabels),
lot.currentBid() lot.currentBid()
@@ -363,9 +363,9 @@ class IntegrationTest {
@Order(9) @Order(9)
@DisplayName("Integration: Handle rapid concurrent updates") @DisplayName("Integration: Handle rapid concurrent updates")
void testConcurrentOperations() throws InterruptedException, SQLException { void testConcurrentOperations() throws InterruptedException, SQLException {
Thread auctionThread = new Thread(() -> { var auctionThread = new Thread(() -> {
try { try {
for (int i = 0; i < 10; i++) { for (var i = 0; i < 10; i++) {
db.upsertAuction(new AuctionInfo( db.upsertAuction(new AuctionInfo(
60000 + i, "Concurrent Auction " + i, "Test, NL", "Test", "NL", 60000 + i, "Concurrent Auction " + i, "Test, NL", "Test", "NL",
"https://example.com/60" + i, "A1", 5, null "https://example.com/60" + i, "A1", 5, null
@@ -376,9 +376,9 @@ class IntegrationTest {
} }
}); });
Thread lotThread = new Thread(() -> { var lotThread = new Thread(() -> {
try { try {
for (int i = 0; i < 10; i++) { for (var i = 0; i < 10; i++) {
db.upsertLot(new Lot( db.upsertLot(new Lot(
60000 + i, 70000 + i, "Concurrent Lot " + i, "Desc", "", "", 0, "Cat", 60000 + i, 70000 + i, "Concurrent Lot " + i, "Desc", "", "", 0, "Cat",
100.0 * i, "EUR", "https://example.com/70" + i, null, false 100.0 * i, "EUR", "https://example.com/70" + i, null, false
@@ -398,11 +398,11 @@ class IntegrationTest {
var auctions = db.getAllAuctions(); var auctions = db.getAllAuctions();
var lots = db.getAllLots(); var lots = db.getAllLots();
long auctionCount = auctions.stream() var auctionCount = auctions.stream()
.filter(a -> a.auctionId() >= 60000 && a.auctionId() < 60010) .filter(a -> a.auctionId() >= 60000 && a.auctionId() < 60010)
.count(); .count();
long lotCount = lots.stream() var lotCount = lots.stream()
.filter(l -> l.lotId() >= 70000 && l.lotId() < 70010) .filter(l -> l.lotId() >= 70000 && l.lotId() < 70010)
.count(); .count();