优化
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
package com.baiyue.lastleg.masterdata;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class OverseasMasterDataOpenApiContractTest {
|
||||
@Test
|
||||
void documentsExchangeRateAndVehicleApisWithoutDeliveryFulfillment() throws Exception {
|
||||
String yaml = Files.readString(Path.of("src/main/resources/openapi/overseas-master-data-v1.yaml"));
|
||||
assertThat(yaml).contains("/api/platform/v1/last-leg/master-data/overseas-quotes:")
|
||||
.contains("缓存合作仓目录30分钟")
|
||||
.contains("/api/platform/v1/last-leg/master-data/exchange-rates:")
|
||||
.contains("/api/platform/v1/last-leg/master-data/vehicles:")
|
||||
.contains("platform:overseas-master-data:exchange-rate:export")
|
||||
.contains("platform:overseas-master-data:vehicle:status")
|
||||
.contains("不包含派送履约或车辆更换历史")
|
||||
.doesNotContain("deliveryOrders:")
|
||||
.doesNotContain("replacementHistory:");
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baiyue.lastleg.masterdata.exchange;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class MonthlyExchangeRateSqlContractTest {
|
||||
@Test
|
||||
void baselineContainsRateAndHistoryTablesWithOptimisticLock() throws Exception {
|
||||
String sql = Files.readString(Path.of("src/main/resources/db/lastleg.sql"));
|
||||
assertThat(sql).contains("CREATE TABLE IF NOT EXISTS ll_monthly_exchange_rate (")
|
||||
.contains("UNIQUE KEY uk_ll_exchange_rate_month (rate_month)")
|
||||
.contains("record_version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本'")
|
||||
.contains("CREATE TABLE IF NOT EXISTS ll_monthly_exchange_rate_history (");
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.baiyue.lastleg.masterdata.exchange.controller;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PlatformMonthlyExchangeRateControllerContractTest {
|
||||
@Test
|
||||
void exposesStablePlatformBaseAndCanonicalAuthorities() {
|
||||
RequestMapping base = PlatformMonthlyExchangeRateController.class.getAnnotation(RequestMapping.class);
|
||||
assertThat(base.value()).containsExactly("/api/platform/v1/last-leg/master-data/exchange-rates");
|
||||
Map<String, String> authorities = Stream.of(PlatformMonthlyExchangeRateController.class.getDeclaredMethods())
|
||||
.filter(method -> method.isAnnotationPresent(PreAuthorize.class))
|
||||
.collect(Collectors.toMap(method -> method.getName(), method -> method.getAnnotation(PreAuthorize.class).value()));
|
||||
assertThat(authorities.get("page")).contains("platform:overseas-master-data:exchange-rate:list");
|
||||
assertThat(authorities.get("summary")).contains("platform:overseas-master-data:exchange-rate:list");
|
||||
assertThat(authorities.get("detail")).contains("platform:overseas-master-data:exchange-rate:list");
|
||||
assertThat(authorities.get("create")).contains("platform:overseas-master-data:exchange-rate:create");
|
||||
assertThat(authorities.get("update")).contains("platform:overseas-master-data:exchange-rate:edit");
|
||||
assertThat(authorities.get("status")).contains("platform:overseas-master-data:exchange-rate:status");
|
||||
assertThat(authorities.get("export")).contains("platform:overseas-master-data:exchange-rate:export");
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.baiyue.lastleg.masterdata.exchange.service;
|
||||
|
||||
import com.baiyue.lastleg.masterdata.exchange.dto.MonthlyExchangeRateDtos;
|
||||
import com.baiyue.lastleg.masterdata.exchange.entity.MonthlyExchangeRate;
|
||||
import com.baiyue.lastleg.masterdata.exchange.mapper.MonthlyExchangeRateHistoryMapper;
|
||||
import com.baiyue.lastleg.masterdata.exchange.mapper.MonthlyExchangeRateMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class MonthlyExchangeRateServiceTest {
|
||||
private MonthlyExchangeRateMapper mapper;
|
||||
private MonthlyExchangeRateService service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
mapper = mock(MonthlyExchangeRateMapper.class);
|
||||
service = new MonthlyExchangeRateService();
|
||||
ReflectionTestUtils.setField(service, "rates", mapper);
|
||||
ReflectionTestUtils.setField(service, "histories", mock(MonthlyExchangeRateHistoryMapper.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsStaleVersion() {
|
||||
MonthlyExchangeRate value = new MonthlyExchangeRate(); value.setRecordVersion(4L); value.setRateMonth("2026-08");
|
||||
when(mapper.lockMonth("2026-08")).thenReturn(value);
|
||||
var request = new MonthlyExchangeRateDtos.Update(3L, new BigDecimal("7.18000000"), null);
|
||||
assertThatThrownBy(() -> service.update("2026-08", "9", request))
|
||||
.isInstanceOf(ResponseStatusException.class).hasMessageContaining("409 CONFLICT");
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.baiyue.lastleg.masterdata.quote.controller;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PlatformOverseasQuoteControllerContractTest {
|
||||
@Test
|
||||
void exposesStablePlatformBaseAndCanonicalAuthorities() {
|
||||
RequestMapping base = PlatformOverseasQuoteController.class.getAnnotation(RequestMapping.class);
|
||||
assertThat(base.value()).containsExactly("/api/platform/v1/last-leg/master-data/overseas-quotes");
|
||||
Map<String, String> authorities = Stream.of(PlatformOverseasQuoteController.class.getDeclaredMethods())
|
||||
.filter(method -> method.isAnnotationPresent(PreAuthorize.class))
|
||||
.collect(Collectors.toMap(method -> method.getName(),
|
||||
method -> method.getAnnotation(PreAuthorize.class).value()));
|
||||
assertThat(authorities.get("page")).contains("platform:overseas-master-data:quote:list");
|
||||
assertThat(authorities.get("detail")).contains("platform:overseas-master-data:quote:list");
|
||||
assertThat(authorities.get("warehouseOptions")).contains("platform:overseas-master-data:quote:list");
|
||||
assertThat(authorities.get("create")).contains("platform:overseas-master-data:quote:create");
|
||||
assertThat(authorities.get("update")).contains("platform:overseas-master-data:quote:edit");
|
||||
assertThat(authorities.get("status")).contains("platform:overseas-master-data:quote:status");
|
||||
assertThat(authorities.get("export")).contains("platform:overseas-master-data:quote:export");
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.baiyue.lastleg.masterdata.quote.service;
|
||||
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import com.baiyue.lastleg.masterdata.quote.client.DomesticPartnerWarehouseClient;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class PartnerWarehouseDirectoryTest {
|
||||
@Mock private DomesticPartnerWarehouseClient client;
|
||||
private PartnerWarehouseDirectory directory;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
directory = new PartnerWarehouseDirectory();
|
||||
ReflectionTestUtils.setField(directory, "client", client);
|
||||
ReflectionTestUtils.setField(directory, "internalToken", "internal-token");
|
||||
ReflectionTestUtils.setField(directory, "ttl", Duration.ofMinutes(30));
|
||||
ReflectionTestUtils.setField(directory, "clock", Clock.fixed(
|
||||
Instant.parse("2026-08-20T00:00:00Z"), ZoneOffset.UTC));
|
||||
}
|
||||
|
||||
@Test
|
||||
void cachesDomesticOptionsForThirtyMinutesAndReturnsIdsAsStrings() {
|
||||
when(client.activePartners("internal-token")).thenReturn(ApiResponse.success(List.of(
|
||||
new DomesticPartnerWarehouseClient.Option(Long.valueOf("9007199254740993"),
|
||||
"US-LAX", "洛杉矶合作仓", "US"))));
|
||||
|
||||
assertThat(directory.options()).singleElement().satisfies(option -> {
|
||||
assertThat(option.warehouseId()).isEqualTo("9007199254740993");
|
||||
assertThat(option.warehouseCode()).isEqualTo("US-LAX");
|
||||
assertThat(option.warehouseName()).isEqualTo("洛杉矶合作仓");
|
||||
assertThat(option.countryCode()).isEqualTo("US");
|
||||
});
|
||||
directory.options();
|
||||
verify(client, times(1)).activePartners("internal-token");
|
||||
|
||||
ReflectionTestUtils.setField(directory, "clock", Clock.fixed(
|
||||
Instant.parse("2026-08-20T00:30:01Z"), ZoneOffset.UTC));
|
||||
directory.options();
|
||||
verify(client, times(2)).activePartners("internal-token");
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.baiyue.lastleg.masterdata.vehicle;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class VehicleSqlContractTest {
|
||||
@Test
|
||||
void baselineContainsVehicleMasterDataWithoutDeliveryHistory() throws Exception {
|
||||
String sql = Files.readString(Path.of("src/main/resources/db/lastleg.sql"));
|
||||
String vehicleSql = sql.substring(sql.indexOf("CREATE TABLE IF NOT EXISTS ll_vehicle ("));
|
||||
assertThat(vehicleSql).contains("UNIQUE KEY uk_ll_vehicle_plate (plate_number)")
|
||||
.contains("record_version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本'")
|
||||
.contains("ownership VARCHAR(16) NOT NULL")
|
||||
.doesNotContain("CREATE TABLE IF NOT EXISTS ll_vehicle_delivery")
|
||||
.doesNotContain("CREATE TABLE IF NOT EXISTS ll_vehicle_replacement");
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baiyue.lastleg.masterdata.vehicle.controller;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PlatformVehicleControllerContractTest {
|
||||
@Test
|
||||
void exposesStablePlatformBaseAndCanonicalAuthorities() {
|
||||
RequestMapping base = PlatformVehicleController.class.getAnnotation(RequestMapping.class);
|
||||
assertThat(base.value()).containsExactly("/api/platform/v1/last-leg/master-data/vehicles");
|
||||
Map<String, String> authorities = Stream.of(PlatformVehicleController.class.getDeclaredMethods())
|
||||
.filter(method -> method.isAnnotationPresent(PreAuthorize.class))
|
||||
.collect(Collectors.toMap(method -> method.getName(), method -> method.getAnnotation(PreAuthorize.class).value()));
|
||||
assertThat(authorities.get("page")).contains("platform:overseas-master-data:vehicle:list");
|
||||
assertThat(authorities.get("detail")).contains("platform:overseas-master-data:vehicle:list");
|
||||
assertThat(authorities.get("create")).contains("platform:overseas-master-data:vehicle:create");
|
||||
assertThat(authorities.get("update")).contains("platform:overseas-master-data:vehicle:edit");
|
||||
assertThat(authorities.get("status")).contains("platform:overseas-master-data:vehicle:status");
|
||||
assertThat(authorities.get("export")).contains("platform:overseas-master-data:vehicle:export");
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.baiyue.lastleg.masterdata.vehicle.service;
|
||||
|
||||
import com.baiyue.lastleg.masterdata.vehicle.dto.VehicleDtos;
|
||||
import com.baiyue.lastleg.masterdata.vehicle.entity.Vehicle;
|
||||
import com.baiyue.lastleg.masterdata.vehicle.mapper.VehicleMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class VehicleServiceTest {
|
||||
private VehicleMapper mapper;
|
||||
private VehicleService service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
mapper = mock(VehicleMapper.class);
|
||||
service = new VehicleService();
|
||||
ReflectionTestUtils.setField(service, "vehicles", mapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsStaleVersionBeforeUpdating() {
|
||||
when(mapper.lockById(1L)).thenReturn(vehicle(3L, 1000L));
|
||||
VehicleDtos.Update request = update(2L, 1000L);
|
||||
assertThatThrownBy(() -> service.update(1L, "9", request))
|
||||
.isInstanceOf(ResponseStatusException.class)
|
||||
.hasMessageContaining("409 CONFLICT");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsDecreasingOdometer() {
|
||||
when(mapper.lockById(1L)).thenReturn(vehicle(3L, 1000L));
|
||||
VehicleDtos.Update request = update(3L, 999L);
|
||||
assertThatThrownBy(() -> service.update(1L, "9", request))
|
||||
.isInstanceOf(ResponseStatusException.class)
|
||||
.hasMessageContaining("400 BAD_REQUEST");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsUnknownStatus() {
|
||||
when(mapper.lockById(1L)).thenReturn(vehicle(3L, 1000L));
|
||||
assertThatThrownBy(() -> service.changeStatus(1L, "9", new VehicleDtos.ChangeStatus("BUSY", 3L)))
|
||||
.isInstanceOf(ResponseStatusException.class)
|
||||
.hasMessageContaining("400 BAD_REQUEST");
|
||||
}
|
||||
|
||||
private static VehicleDtos.Update update(long version, long mileage) {
|
||||
return new VehicleDtos.Update(version, "ABC-001", "Box Truck", new BigDecimal("12.50"), mileage,
|
||||
"Driver", "123", "OVERSEAS", "OWNED", null);
|
||||
}
|
||||
|
||||
private static Vehicle vehicle(long version, long mileage) {
|
||||
Vehicle value = new Vehicle(); value.setId(1L); value.setRecordVersion(version); value.setMileageKm(mileage);
|
||||
value.setStatus("IN_SERVICE"); return value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user