This commit is contained in:
2026-08-26 13:58:33 +08:00
parent fc0a6ea7ca
commit 4398e8b347
78 changed files with 920 additions and 1549 deletions
@@ -0,0 +1,63 @@
package com.baiyue.warehouse.service;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.warehouse.client.DomesticWarehouseDirectoryClient;
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.Duration;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class DomesticWarehouseDirectoryTest {
@Mock DomesticWarehouseDirectoryClient client;
private DomesticWarehouseDirectory directory;
@BeforeEach
void setUp() {
directory = new DomesticWarehouseDirectory();
ReflectionTestUtils.setField(directory, "client", client);
ReflectionTestUtils.setField(directory, "internalToken", "internal-token");
ReflectionTestUtils.setField(directory, "ttl", Duration.ofMinutes(30));
}
@Test
void cachesPositiveWarehouseForThirtyMinutes() {
var warehouse = new DomesticWarehouseDirectoryClient.WarehouseReference(
92L, "US-LAX-01", "Los Angeles", "US", "ACTIVE");
when(client.activeSharedWarehouse("internal-token", 92L))
.thenReturn(ApiResponse.success(warehouse));
assertThat(directory.required(92L)).isEqualTo(directory.required(92L));
verify(client, times(1)).activeSharedWarehouse("internal-token", 92L);
}
@Test
void doesNotCacheMissingWarehouse() {
when(client.activeSharedWarehouse("internal-token", 93L))
.thenReturn(ApiResponse.success(null));
assertThatThrownBy(() -> directory.required(93L)).isInstanceOf(BizException.class);
assertThatThrownBy(() -> directory.required(93L)).isInstanceOf(BizException.class);
verify(client, times(2)).activeSharedWarehouse("internal-token", 93L);
}
@Test
void emptyOptionDirectoryDoesNotCreatePositiveCacheEntries() {
when(client.activeSharedWarehouses("internal-token"))
.thenReturn(ApiResponse.success(List.of()));
assertThat(directory.options()).isEmpty();
}
}
@@ -1,109 +0,0 @@
package com.baiyue.warehouse.service;
import com.baiyue.warehouse.dto.WarehouseRequests;
import com.baiyue.warehouse.entity.WarehouseEntity;
import com.baiyue.warehouse.entity.WarehouseLocationEntity;
import com.baiyue.warehouse.entity.ServiceCapabilityEntity;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.warehouse.repository.WarehouseRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class WarehouseApplicationServiceTest {
@Mock WarehouseRepository repository;
private WarehouseApplicationService service;
@BeforeEach
void setUp() {
service = new WarehouseApplicationService();
ReflectionTestUtils.setField(service, "repository", repository);
}
@Test
void warehouseCreationAlsoCreatesActiveDefaultVirtualLocation() {
doAnswer(call -> {
((WarehouseEntity) call.getArgument(0)).setId(20001L);
return null;
}).when(repository).insertWarehouse(any());
service.create(request());
ArgumentCaptor<WarehouseLocationEntity> location = ArgumentCaptor.forClass(WarehouseLocationEntity.class);
verify(repository).insertLocation(location.capture());
assertThat(location.getValue().getCustomerId()).isEqualTo(10001L);
assertThat(location.getValue().getWarehouseId()).isEqualTo(20001L);
assertThat(location.getValue().getLocationCode()).isEqualTo("LOC-US-LAX-01-DEFAULT");
assertThat(location.getValue().getLocationType()).isEqualTo("VIRTUAL");
assertThat(location.getValue().getStatus()).isEqualTo("ACTIVE");
}
@Test
void platformWarehousePagePassesCustomerScopedQueryToRepository() {
WarehouseRequests.QueryRequest query = new WarehouseRequests.QueryRequest(10001L, 1, 20, "US", null, "ACTIVE");
when(repository.pageAll(query)).thenReturn(new com.baiyue.common.core.api.PageResult<>(List.of(), 1, 20, 0, 0));
service.pageAll(query);
verify(repository).pageAll(query);
}
@Test
void sharedReceivingWarehouseMustBeOverseasAndResolvesCanonicalReference() {
WarehouseRequests.SaveRequest shared = sharedRequest("OVERSEAS", true);
doAnswer(call -> { ((WarehouseEntity) call.getArgument(0)).setId(900L); return null; })
.when(repository).insertWarehouse(any());
assertThat(service.create(shared)).isEqualTo(900L);
WarehouseEntity warehouse = new WarehouseEntity(); warehouse.setId(900L); warehouse.setCustomerId(0L);
warehouse.setWarehouseCode("SHARED-LAX"); warehouse.setWarehouseName("Shared LAX");
warehouse.setWarehouseType("OVERSEAS"); warehouse.setStatus("ACTIVE");
ServiceCapabilityEntity receiving = new ServiceCapabilityEntity();
receiving.setCapabilityCode("RECEIVING"); receiving.setEnabled(true);
when(repository.findOwned(0L, 900L)).thenReturn(warehouse);
when(repository.findCapabilities(0L, 900L)).thenReturn(List.of(receiving));
assertThat(service.activeSharedReference(900L).warehouseName()).isEqualTo("Shared LAX");
}
@Test
void sharedWarehouseRejectsNonOverseasOrMissingReceivingCapability() {
assertThatThrownBy(() -> service.create(sharedRequest("FBA", true))).isInstanceOf(BizException.class);
assertThatThrownBy(() -> service.create(sharedRequest("OVERSEAS", false))).isInstanceOf(BizException.class);
}
private static WarehouseRequests.SaveRequest request() {
WarehouseRequests.AddressRequest address = new WarehouseRequests.AddressRequest(
"WAREHOUSE", "US", "CA", "Los Angeles", null, "90001",
"1 Logistics Ave", null, null, null);
return new WarehouseRequests.SaveRequest(10001L, "US-LAX-01", "LAX Warehouse",
"OVERSEAS", "US", "America/Los_Angeles", null, null, null,
"ACTIVE", null, address, List.of());
}
private static WarehouseRequests.SaveRequest sharedRequest(String type, boolean receiving) {
WarehouseRequests.AddressRequest address = new WarehouseRequests.AddressRequest(
"WAREHOUSE", "US", "CA", "Los Angeles", null, "90001",
"1 Logistics Ave", null, null, null);
List<WarehouseRequests.CapabilityRequest> capabilities = receiving
? List.of(new WarehouseRequests.CapabilityRequest("RECEIVING", "收货", true, null, null))
: List.of();
return new WarehouseRequests.SaveRequest(0L, "SHARED-LAX", "Shared LAX", type,
"US", "America/Los_Angeles", null, null, null, "ACTIVE", null, address, capabilities);
}
}
@@ -7,7 +7,7 @@ import com.baiyue.warehouse.dto.LocationRequests;
import com.baiyue.warehouse.dto.PalletRequests;
import com.baiyue.warehouse.entity.WarehouseLocationEntity;
import com.baiyue.warehouse.entity.WarehousePalletEntity;
import com.baiyue.warehouse.entity.WarehouseEntity;
import com.baiyue.warehouse.dto.SharedWarehouseReference;
import com.baiyue.warehouse.repository.WarehouseResourceRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -33,6 +33,8 @@ class WarehouseResourceServiceTest {
@Mock
private WarehouseResourceRepository repository;
@Mock
private DomesticWarehouseDirectory warehouseDirectory;
private WarehouseResourceService service;
@@ -40,6 +42,9 @@ class WarehouseResourceServiceTest {
void setUp() {
service = new WarehouseResourceService();
ReflectionTestUtils.setField(service, "repository", repository);
ReflectionTestUtils.setField(service, "warehouseDirectory", warehouseDirectory);
org.mockito.Mockito.lenient().when(warehouseDirectory.required(WAREHOUSE))
.thenReturn(warehouse());
}
@Test
@@ -65,7 +70,6 @@ class WarehouseResourceServiceTest {
@Test
void createsLocationWithSnowflakeAssignedByMapper() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
doAnswer(invocation -> {
((WarehouseLocationEntity) invocation.getArgument(0)).setId(2089000000000000001L);
return null;
@@ -82,8 +86,6 @@ class WarehouseResourceServiceTest {
@Test
void platformPalletUsesPublicScopeAgainstAnyExistingWarehouse() {
WarehouseEntity warehouse = warehouse();
when(repository.findWarehouseById(WAREHOUSE)).thenReturn(warehouse);
WarehouseLocationEntity location = new WarehouseLocationEntity();
location.setId(30001L);
when(repository.findLocation(0L, WAREHOUSE, 30001L)).thenReturn(location);
@@ -99,7 +101,8 @@ class WarehouseResourceServiceTest {
@Test
void rejectsResourceAccessWhenWarehouseDoesNotBelongToTenant() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(false);
when(warehouseDirectory.required(WAREHOUSE)).thenThrow(new BizException(
com.baiyue.common.core.api.ResultCode.NOT_FOUND, "仓库不存在"));
assertThatThrownBy(() -> service.createLocation(TENANT, WAREHOUSE, locationRequest("A-01")))
.isInstanceOf(BizException.class)
@@ -109,7 +112,6 @@ class WarehouseResourceServiceTest {
@Test
void rejectsDuplicateLocationCodeWithinWarehouse() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
when(repository.locationCodeExists(TENANT, WAREHOUSE, "A-01", null)).thenReturn(true);
assertThatThrownBy(() -> service.createLocation(TENANT, WAREHOUSE, locationRequest("A-01")))
@@ -119,8 +121,6 @@ class WarehouseResourceServiceTest {
@Test
void palletDefaultsToTwoCubicMetresAndBindsOwnedLocation() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
when(repository.findWarehouse(TENANT, WAREHOUSE)).thenReturn(warehouse());
WarehouseLocationEntity location = new WarehouseLocationEntity();
location.setId(30001L);
when(repository.findLocation(TENANT, WAREHOUSE, 30001L)).thenReturn(location);
@@ -142,8 +142,6 @@ class WarehouseResourceServiceTest {
@Test
void rejectsLocationFromAnotherWarehouseWhenBindingPallet() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
when(repository.findWarehouse(TENANT, WAREHOUSE)).thenReturn(warehouse());
when(repository.findLocation(TENANT, WAREHOUSE, 30002L)).thenReturn(null);
assertThatThrownBy(() -> service.createPallet(TENANT, WAREHOUSE,
@@ -156,7 +154,6 @@ class WarehouseResourceServiceTest {
@Test
void preventsDeletingLocationThatStillHasPallets() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
when(repository.findLocation(TENANT, WAREHOUSE, 30001L)).thenReturn(new WarehouseLocationEntity());
when(repository.locationHasPallets(TENANT, WAREHOUSE, 30001L)).thenReturn(true);
@@ -168,7 +165,6 @@ class WarehouseResourceServiceTest {
@Test
void preventsDeletingOccupiedPallet() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
WarehousePalletEntity pallet = new WarehousePalletEntity();
pallet.setStatus("OCCUPIED");
when(repository.findPallet(TENANT, WAREHOUSE, 40001L)).thenReturn(pallet);
@@ -181,7 +177,6 @@ class WarehouseResourceServiceTest {
@Test
void preventsDeletingScrappedPalletSoItsIdentityCannotBeReused() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
WarehousePalletEntity pallet = new WarehousePalletEntity();
pallet.setStatus("SCRAPPED");
when(repository.findPallet(TENANT, WAREHOUSE, 40003L)).thenReturn(pallet);
@@ -194,7 +189,6 @@ class WarehouseResourceServiceTest {
@Test
void rejectsUnknownPalletStatus() {
when(repository.findWarehouse(TENANT, WAREHOUSE)).thenReturn(warehouse());
assertThatThrownBy(() -> service.createPallet(TENANT, WAREHOUSE,
new PalletRequests.SaveRequest("PLT-01", "STANDARD", null,
@@ -210,14 +204,12 @@ class WarehouseResourceServiceTest {
@Test
void generatesRestartSafePalletCodeAndUsesDefaultVirtualLocation() {
when(repository.findWarehouse(TENANT, WAREHOUSE)).thenReturn(warehouse());
WarehouseLocationEntity location = new WarehouseLocationEntity();
location.setId(30003L);
location.setLocationType("VIRTUAL");
location.setStatus("ACTIVE");
when(repository.findLocationByCode(TENANT, WAREHOUSE, "LOC-US-LAX-01-DEFAULT"))
.thenReturn(location);
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
when(repository.findLocation(TENANT, WAREHOUSE, 30003L)).thenReturn(location);
service.createPallet(TENANT, WAREHOUSE,
@@ -232,7 +224,6 @@ class WarehouseResourceServiceTest {
@Test
void defaultVirtualLocationIsInsertedIdempotentlyForAnExistingWarehouse() {
when(repository.findWarehouse(TENANT, WAREHOUSE)).thenReturn(warehouse());
WarehouseLocationEntity resolved = new WarehouseLocationEntity();
resolved.setId(30004L);
resolved.setLocationType("VIRTUAL");
@@ -252,7 +243,6 @@ class WarehouseResourceServiceTest {
@Test
void rejectsAConflictingDefaultLocationCode() {
when(repository.findWarehouse(TENANT, WAREHOUSE)).thenReturn(warehouse());
WarehouseLocationEntity conflict = new WarehouseLocationEntity();
conflict.setLocationType("STORAGE");
conflict.setStatus("ACTIVE");
@@ -267,7 +257,6 @@ class WarehouseResourceServiceTest {
@Test
void scrappedPalletCannotBeReactivated() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
WarehousePalletEntity existing = new WarehousePalletEntity();
existing.setId(40002L);
existing.setPalletCode("PLT-OLD");
@@ -283,7 +272,6 @@ class WarehouseResourceServiceTest {
@Test
void updatePalletChangesCodeAndFbaWarehouseCode() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
WarehousePalletEntity existing = new WarehousePalletEntity();
existing.setId(40003L);
existing.setPalletCode("PLT-OLD");
@@ -306,7 +294,6 @@ class WarehouseResourceServiceTest {
@Test
void updatePalletRejectsDuplicateCodeInSameWarehouse() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
WarehousePalletEntity existing = new WarehousePalletEntity();
existing.setId(40004L);
existing.setPalletCode("PLT-OLD");
@@ -325,7 +312,6 @@ class WarehouseResourceServiceTest {
@Test
void updatePalletRejectsStaleVersionBeforeMutation() {
when(repository.warehouseOwned(TENANT, WAREHOUSE)).thenReturn(true);
WarehousePalletEntity existing = new WarehousePalletEntity();
existing.setId(40005L);
existing.setPalletCode("PLT-OLD");
@@ -344,11 +330,7 @@ class WarehouseResourceServiceTest {
verify(repository, never()).updatePallet(org.mockito.ArgumentMatchers.any());
}
private static WarehouseEntity warehouse() {
WarehouseEntity warehouse = new WarehouseEntity();
warehouse.setId(WAREHOUSE);
warehouse.setCustomerId(TENANT);
warehouse.setWarehouseCode("US-LAX-01");
return warehouse;
private static SharedWarehouseReference warehouse() {
return new SharedWarehouseReference(WAREHOUSE, "US-LAX-01", "Los Angeles", "ACTIVE");
}
}