refactor: narrow vehicle stat repository contract
This commit is contained in:
@@ -26,8 +26,7 @@ public final class JdbcVehicleStatMetricRepository implements VehicleStatReposit
|
||||
ensureSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveDailyStat(VehicleDailyStatResult result) {
|
||||
private void saveDailyMileageMetric(VehicleDailyStatResult result) {
|
||||
if (result == null || result.dailyMileageKm().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -88,7 +87,7 @@ public final class JdbcVehicleStatMetricRepository implements VehicleStatReposit
|
||||
statDate,
|
||||
OptionalDouble.of(dailyMileageKm),
|
||||
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF);
|
||||
saveDailyStat(result);
|
||||
saveDailyMileageMetric(result);
|
||||
return Optional.of(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ import java.util.Optional;
|
||||
|
||||
public interface VehicleStatRepository {
|
||||
|
||||
void saveDailyStat(VehicleDailyStatResult result);
|
||||
|
||||
Optional<VehicleDailyStatResult> recordDailyMileageSample(String vin, LocalDate statDate, double totalMileageKm);
|
||||
|
||||
Optional<VehicleDailyStatResult> findDailyStat(String vin, LocalDate statDate);
|
||||
|
||||
@@ -5,30 +5,21 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.OptionalDouble;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class JdbcVehicleStatMetricRepositoryTest {
|
||||
|
||||
@Test
|
||||
void upsertsDailyMileageIntoCommonMetricTable() {
|
||||
void recordsDailyMileageIntoCommonMetricTable() {
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(new DriverManagerDataSource(
|
||||
"jdbc:h2:mem:vehicle_stat_metric;MODE=MySQL;DATABASE_TO_LOWER=TRUE;DB_CLOSE_DELAY=-1",
|
||||
"sa",
|
||||
""));
|
||||
JdbcVehicleStatMetricRepository repository = new JdbcVehicleStatMetricRepository(jdbcTemplate);
|
||||
|
||||
repository.saveDailyStat(new VehicleDailyStatResult(
|
||||
"VIN001",
|
||||
LocalDate.of(2026, 6, 30),
|
||||
OptionalDouble.of(12.345),
|
||||
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF));
|
||||
repository.saveDailyStat(new VehicleDailyStatResult(
|
||||
"VIN001",
|
||||
LocalDate.of(2026, 6, 30),
|
||||
OptionalDouble.of(15.5),
|
||||
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF));
|
||||
repository.recordDailyMileageSample("VIN001", LocalDate.of(2026, 6, 30), 100.0);
|
||||
repository.recordDailyMileageSample("VIN001", LocalDate.of(2026, 6, 30), 115.5);
|
||||
|
||||
assertThat(repository.findDailyStat("VIN001", LocalDate.of(2026, 6, 30)))
|
||||
.isPresent()
|
||||
@@ -36,12 +27,12 @@ class JdbcVehicleStatMetricRepositoryTest {
|
||||
.extracting(result -> result.dailyMileageKm().orElseThrow())
|
||||
.isEqualTo(15.5);
|
||||
assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM vehicle_stat_metric", Integer.class))
|
||||
.isEqualTo(1);
|
||||
.isEqualTo(3);
|
||||
assertThat(jdbcTemplate.queryForObject(
|
||||
"SELECT metric_key FROM vehicle_stat_metric WHERE vin = 'VIN001'",
|
||||
"SELECT metric_key FROM vehicle_stat_metric WHERE vin = 'VIN001' AND metric_key = 'daily_mileage_km'",
|
||||
String.class)).isEqualTo("daily_mileage_km");
|
||||
assertThat(jdbcTemplate.queryForObject(
|
||||
"SELECT calculation_method FROM vehicle_stat_metric WHERE vin = 'VIN001'",
|
||||
"SELECT calculation_method FROM vehicle_stat_metric WHERE vin = 'VIN001' AND metric_key = 'daily_mileage_km'",
|
||||
String.class)).isEqualTo("JT808_TOTAL_MILEAGE_DIFF");
|
||||
assertThat(jdbcTemplate.queryForObject("""
|
||||
SELECT COUNT(*)
|
||||
|
||||
@@ -17,11 +17,8 @@ class VehicleStatControllerTest {
|
||||
@Test
|
||||
void returnsDailyStatJson() throws Exception {
|
||||
InMemoryVehicleStatRepository repository = new InMemoryVehicleStatRepository();
|
||||
repository.saveDailyStat(new VehicleDailyStatResult(
|
||||
"VIN001",
|
||||
LocalDate.parse("2026-06-22"),
|
||||
OptionalDouble.of(35.5),
|
||||
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF));
|
||||
repository.recordDailyMileageSample("VIN001", LocalDate.parse("2026-06-22"), 100.0);
|
||||
repository.recordDailyMileageSample("VIN001", LocalDate.parse("2026-06-22"), 135.5);
|
||||
MockMvc mvc = standaloneSetup(new VehicleStatController(repository)).build();
|
||||
|
||||
mvc.perform(get("/api/vehicle-stat/VIN001/daily").param("date", "2026-06-22"))
|
||||
@@ -34,21 +31,19 @@ class VehicleStatControllerTest {
|
||||
|
||||
private static final class InMemoryVehicleStatRepository implements VehicleStatRepository {
|
||||
private final java.util.Map<String, VehicleDailyStatResult> results = new java.util.HashMap<>();
|
||||
|
||||
@Override
|
||||
public void saveDailyStat(VehicleDailyStatResult result) {
|
||||
results.put(result.vin() + ":" + result.statDate(), result);
|
||||
}
|
||||
private final java.util.Map<String, Double> firstTotals = new java.util.HashMap<>();
|
||||
|
||||
@Override
|
||||
public Optional<VehicleDailyStatResult> recordDailyMileageSample(String vin, LocalDate statDate,
|
||||
double totalMileageKm) {
|
||||
String key = vin + ":" + statDate;
|
||||
double firstTotal = firstTotals.computeIfAbsent(key, ignored -> totalMileageKm);
|
||||
VehicleDailyStatResult result = new VehicleDailyStatResult(
|
||||
vin,
|
||||
statDate,
|
||||
OptionalDouble.of(0.0),
|
||||
OptionalDouble.of(totalMileageKm - firstTotal),
|
||||
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF);
|
||||
saveDailyStat(result);
|
||||
results.put(key, result);
|
||||
return Optional.of(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lingniu.ingest.vehiclestat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class VehicleStatRepositoryContractTest {
|
||||
|
||||
@Test
|
||||
void exposesOnlyMileageSampleAndQueryOperations() {
|
||||
assertThat(Arrays.stream(VehicleStatRepository.class.getDeclaredMethods())
|
||||
.map(Method::getName))
|
||||
.containsExactlyInAnyOrder("recordDailyMileageSample", "findDailyStat");
|
||||
}
|
||||
}
|
||||
@@ -101,11 +101,6 @@ class Jt808MileageStreamProcessorTest {
|
||||
private final List<Double> samples = new ArrayList<>();
|
||||
private double firstSample = Double.NaN;
|
||||
|
||||
@Override
|
||||
public void saveDailyStat(VehicleDailyStatResult result) {
|
||||
results.add(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<VehicleDailyStatResult> recordDailyMileageSample(String vin, LocalDate statDate,
|
||||
double totalMileageKm) {
|
||||
|
||||
Reference in New Issue
Block a user