feat: 클라이언트 유량제어/RequestProcessor custom 패키지로 분리
- DJBRequestProcessor: inbound.processor → custom.inbound.processor 이동
- ClientInflowTargetMetricService/Controller: custom.inflow 패키지 신규 생성
클라이언트 메트릭 API(/manage/inflow/client/**)를 InflowTargetMetric*에서 분리
- InflowTargetMetricService/Controller: 클라이언트 관련 메서드/엔드포인트 제거
- InflowTargetBucketService: getClientDualManager() 분리 반영
- standard-message-config.properties: requestProcessor.class 경로 업데이트
- 단위 테스트: ClientInflowTargetMetric{Service,Controller}Test 추가,
기존 테스트에서 클라이언트 케이스 분리
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.eactive.eai.common.inflow.InflowTargetVO;
|
||||
import com.eactive.eai.common.inflow.dual.ClientDualInflowControlManager;
|
||||
import com.eactive.eai.common.inflow.dual.DualCustomBucket;
|
||||
import com.eactive.eai.common.inflow.dual.DualInflowControlManager;
|
||||
|
||||
@@ -21,8 +22,8 @@ import io.github.bucket4j.local.LocalBucket;
|
||||
/**
|
||||
* InflowTargetBucketService 단위 테스트.
|
||||
*
|
||||
* <p>getDualManager()를 protected로 오버라이드하는 내부 테스트 서브클래스를 사용하여
|
||||
* DualInflowControlManager 의존성을 주입한다.
|
||||
* <p>어댑터/인터페이스: getDualManager()를 오버라이드하는 서브클래스 사용.
|
||||
* 클라이언트: getClientDualManager()를 오버라이드하는 서브클래스 사용.
|
||||
*/
|
||||
class InflowTargetBucketServiceTest {
|
||||
|
||||
@@ -33,9 +34,18 @@ class InflowTargetBucketServiceTest {
|
||||
private static InflowTargetBucketService serviceWith(DualInflowControlManager manager) {
|
||||
return new InflowTargetBucketService() {
|
||||
@Override
|
||||
protected DualInflowControlManager getDualManager() {
|
||||
return manager;
|
||||
}
|
||||
protected DualInflowControlManager getDualManager() { return manager; }
|
||||
@Override
|
||||
protected ClientDualInflowControlManager getClientDualManager() { return null; }
|
||||
};
|
||||
}
|
||||
|
||||
private static InflowTargetBucketService serviceWithClient(ClientDualInflowControlManager manager) {
|
||||
return new InflowTargetBucketService() {
|
||||
@Override
|
||||
protected DualInflowControlManager getDualManager() { return manager; }
|
||||
@Override
|
||||
protected ClientDualInflowControlManager getClientDualManager() { return manager; }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -98,12 +108,12 @@ class InflowTargetBucketServiceTest {
|
||||
|
||||
@Test
|
||||
void getClientBucketStatus_managerIsNull_returnsNull() {
|
||||
assertNull(serviceWith(null).getClientBucketStatus("CLIENT_A"));
|
||||
assertNull(serviceWithClient(null).getClientBucketStatus("CLIENT_A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllClientBucketStatus_managerIsNull_returnsEmptyList() {
|
||||
assertTrue(serviceWith(null).getAllClientBucketStatus().isEmpty());
|
||||
assertTrue(serviceWithClient(null).getAllClientBucketStatus().isEmpty());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
@@ -128,10 +138,10 @@ class InflowTargetBucketServiceTest {
|
||||
|
||||
@Test
|
||||
void getClientBucketStatus_notFound_returnsNull() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
ClientDualInflowControlManager manager = mock(ClientDualInflowControlManager.class);
|
||||
when(manager.getClientBucket("CLIENT_A")).thenReturn(null);
|
||||
|
||||
assertNull(serviceWith(manager).getClientBucketStatus("CLIENT_A"));
|
||||
assertNull(serviceWithClient(manager).getClientBucketStatus("CLIENT_A"));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
@@ -168,10 +178,10 @@ class InflowTargetBucketServiceTest {
|
||||
|
||||
@Test
|
||||
void getClientBucketStatus_found_mapsClientType() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
ClientDualInflowControlManager manager = mock(ClientDualInflowControlManager.class);
|
||||
when(manager.getClientBucket("CLIENT_A")).thenReturn(makeDualBucket("CLIENT_A", 50, 5000));
|
||||
|
||||
TargetBucketStatusDTO dto = serviceWith(manager).getClientBucketStatus("CLIENT_A");
|
||||
TargetBucketStatusDTO dto = serviceWithClient(manager).getClientBucketStatus("CLIENT_A");
|
||||
|
||||
assertNotNull(dto);
|
||||
assertEquals("CLIENT_A", dto.getTargetId());
|
||||
@@ -189,10 +199,10 @@ class InflowTargetBucketServiceTest {
|
||||
InflowTargetVO vo = makeVO("C1", 0, 1000, "DAY", true);
|
||||
DualCustomBucket bucket = new DualCustomBucket(null, freshBucket(1000), vo);
|
||||
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
ClientDualInflowControlManager manager = mock(ClientDualInflowControlManager.class);
|
||||
when(manager.getClientBucket("C1")).thenReturn(bucket);
|
||||
|
||||
TargetBucketStatusDTO dto = serviceWith(manager).getClientBucketStatus("C1");
|
||||
TargetBucketStatusDTO dto = serviceWithClient(manager).getClientBucketStatus("C1");
|
||||
|
||||
assertEquals(1, dto.getBuckets().size());
|
||||
assertEquals("threshold", dto.getBuckets().get(0).getType());
|
||||
@@ -203,10 +213,10 @@ class InflowTargetBucketServiceTest {
|
||||
InflowTargetVO vo = makeVO("C2", 100, 0, "SEC", true);
|
||||
DualCustomBucket bucket = new DualCustomBucket(freshBucket(100), null, vo);
|
||||
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
ClientDualInflowControlManager manager = mock(ClientDualInflowControlManager.class);
|
||||
when(manager.getClientBucket("C2")).thenReturn(bucket);
|
||||
|
||||
TargetBucketStatusDTO dto = serviceWith(manager).getClientBucketStatus("C2");
|
||||
TargetBucketStatusDTO dto = serviceWithClient(manager).getClientBucketStatus("C2");
|
||||
|
||||
assertEquals(1, dto.getBuckets().size());
|
||||
assertEquals("perSecond", dto.getBuckets().get(0).getType());
|
||||
@@ -214,10 +224,10 @@ class InflowTargetBucketServiceTest {
|
||||
|
||||
@Test
|
||||
void toDto_bothBuckets_bucketInfoHasTwoEntries() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
ClientDualInflowControlManager manager = mock(ClientDualInflowControlManager.class);
|
||||
when(manager.getClientBucket("C3")).thenReturn(makeDualBucket("C3", 100, 5000));
|
||||
|
||||
TargetBucketStatusDTO dto = serviceWith(manager).getClientBucketStatus("C3");
|
||||
TargetBucketStatusDTO dto = serviceWithClient(manager).getClientBucketStatus("C3");
|
||||
|
||||
assertEquals(2, dto.getBuckets().size());
|
||||
assertEquals("perSecond", dto.getBuckets().get(0).getType());
|
||||
@@ -233,10 +243,10 @@ class InflowTargetBucketServiceTest {
|
||||
InflowTargetVO vo = makeVO("C4", 0, 100, "DAY", true);
|
||||
DualCustomBucket bucket = new DualCustomBucket(null, exhaustedBucket(100), vo);
|
||||
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
ClientDualInflowControlManager manager = mock(ClientDualInflowControlManager.class);
|
||||
when(manager.getClientBucket("C4")).thenReturn(bucket);
|
||||
|
||||
TargetBucketStatusDTO dto = serviceWith(manager).getClientBucketStatus("C4");
|
||||
TargetBucketStatusDTO dto = serviceWithClient(manager).getClientBucketStatus("C4");
|
||||
|
||||
GroupBucketStatusDTO.BucketInfo info = dto.getBuckets().get(0);
|
||||
assertEquals(0, info.getAvailableTokens());
|
||||
@@ -248,10 +258,10 @@ class InflowTargetBucketServiceTest {
|
||||
InflowTargetVO vo = makeVO("C5", 0, 100, "DAY", true);
|
||||
DualCustomBucket bucket = new DualCustomBucket(null, freshBucket(100), vo);
|
||||
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
ClientDualInflowControlManager manager = mock(ClientDualInflowControlManager.class);
|
||||
when(manager.getClientBucket("C5")).thenReturn(bucket);
|
||||
|
||||
TargetBucketStatusDTO dto = serviceWith(manager).getClientBucketStatus("C5");
|
||||
TargetBucketStatusDTO dto = serviceWithClient(manager).getClientBucketStatus("C5");
|
||||
|
||||
GroupBucketStatusDTO.BucketInfo info = dto.getBuckets().get(0);
|
||||
assertEquals(100, info.getAvailableTokens());
|
||||
@@ -280,13 +290,13 @@ class InflowTargetBucketServiceTest {
|
||||
|
||||
@Test
|
||||
void getAllClientBucketStatus_twoEntries_returnsBoth() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
ClientDualInflowControlManager manager = mock(ClientDualInflowControlManager.class);
|
||||
Map<String, DualCustomBucket> map = new ConcurrentHashMap<>();
|
||||
map.put("CLIENT_A", makeDualBucket("CLIENT_A", 10, 1000));
|
||||
map.put("CLIENT_B", makeDualBucket("CLIENT_B", 20, 2000));
|
||||
when(manager.getClientBucketMap()).thenReturn(map);
|
||||
|
||||
List<TargetBucketStatusDTO> result = serviceWith(manager).getAllClientBucketStatus();
|
||||
List<TargetBucketStatusDTO> result = serviceWithClient(manager).getAllClientBucketStatus();
|
||||
|
||||
assertEquals(2, result.size());
|
||||
}
|
||||
|
||||
@@ -210,92 +210,4 @@ class InflowTargetMetricControllerTest {
|
||||
|
||||
verify(mockService, times(1)).resetAllInterfaceMetrics();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 클라이언트 — 단일 조회
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void getClientMetric_found_successTrueAndDataPresent() {
|
||||
TargetMetricDTO dto = makeDTO("C1", "CLIENT", 300, 50, 20);
|
||||
when(mockService.getClientMetric("C1")).thenReturn(dto);
|
||||
|
||||
Map<String, Object> body = body(controller.getClientMetric("C1"));
|
||||
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertSame(dto, body.get("data"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getClientMetric_notFound_successFalseWithMessage() {
|
||||
when(mockService.getClientMetric("GHOST")).thenReturn(null);
|
||||
|
||||
Map<String, Object> body = body(controller.getClientMetric("GHOST"));
|
||||
|
||||
assertEquals(Boolean.FALSE, body.get("success"));
|
||||
assertTrue(body.get("message").toString().contains("GHOST"));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 클라이언트 — 전체 조회
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void getAllClientMetrics_returnsListAndCount() {
|
||||
List<TargetMetricDTO> list = Arrays.asList(
|
||||
makeDTO("C1", "CLIENT", 100, 5, 5),
|
||||
makeDTO("C2", "CLIENT", 200, 0, 0),
|
||||
makeDTO("C3", "CLIENT", 50, 10, 0)
|
||||
);
|
||||
when(mockService.getAllClientMetrics()).thenReturn(list);
|
||||
|
||||
Map<String, Object> body = body(controller.getAllClientMetrics());
|
||||
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertSame(list, body.get("data"));
|
||||
assertEquals(3, body.get("count"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllClientMetrics_emptyList_countZero() {
|
||||
when(mockService.getAllClientMetrics()).thenReturn(Collections.emptyList());
|
||||
|
||||
Map<String, Object> body = body(controller.getAllClientMetrics());
|
||||
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertEquals(0, body.get("count"));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 클라이언트 — reset
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void resetClientMetric_success_successTrue() {
|
||||
when(mockService.resetClientMetric("C1")).thenReturn(true);
|
||||
|
||||
Map<String, Object> body = body(controller.resetClientMetric("C1"));
|
||||
|
||||
assertEquals(Boolean.TRUE, body.get("success"));
|
||||
assertTrue(body.get("message").toString().contains("C1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetClientMetric_notFound_successFalse() {
|
||||
when(mockService.resetClientMetric("GHOST")).thenReturn(false);
|
||||
|
||||
Map<String, Object> body = body(controller.resetClientMetric("GHOST"));
|
||||
|
||||
assertEquals(Boolean.FALSE, body.get("success"));
|
||||
assertTrue(body.get("message").toString().contains("GHOST"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetAllClientMetrics_callsDelegateOnce() {
|
||||
doNothing().when(mockService).resetAllClientMetrics();
|
||||
|
||||
controller.resetAllClientMetrics();
|
||||
|
||||
verify(mockService, times(1)).resetAllClientMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ import com.eactive.eai.common.inflow.dual.DualInflowControlManager;
|
||||
/**
|
||||
* InflowTargetMetricService 단위 테스트.
|
||||
*
|
||||
* <p>getDualManager()를 오버라이드하여 DualInflowControlManager 의존성을 주입한다.
|
||||
* <p>어댑터/인터페이스 테스트는 getDualManager()를 오버라이드하여 DualInflowControlManager 주입.
|
||||
*/
|
||||
class InflowTargetMetricServiceTest {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// 테스트용 서브클래스
|
||||
// 테스트용 서브클래스 — 어댑터/인터페이스용
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private static InflowTargetMetricService serviceWith(DualInflowControlManager manager) {
|
||||
@@ -76,11 +76,6 @@ class InflowTargetMetricServiceTest {
|
||||
assertNull(serviceWith(null).getInterfaceMetric("IF1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getClientMetric_managerIsNull_returnsNull() {
|
||||
assertNull(serviceWith(null).getClientMetric("C1"));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 어댑터 — 단일 조회
|
||||
// =========================================================================
|
||||
@@ -271,55 +266,4 @@ class InflowTargetMetricServiceTest {
|
||||
serviceWith(manager).resetAllInterfaceMetrics();
|
||||
verify(manager).resetAllInterfaceMetrics();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 클라이언트 — 단일 조회
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void getClientMetric_found_mapsFields() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getClientInflowThreshold("C1")).thenReturn(makeVO("C1"));
|
||||
when(manager.getClientMetrics("C1")).thenReturn(makeMetrics(200, 30, 20));
|
||||
|
||||
TargetMetricDTO dto = serviceWith(manager).getClientMetric("C1");
|
||||
|
||||
assertNotNull(dto);
|
||||
assertEquals("C1", dto.getTargetId());
|
||||
assertEquals("CLIENT", dto.getTargetType());
|
||||
assertEquals(200, dto.getAllowed());
|
||||
assertEquals(250, dto.getTotalRequests());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getClientMetric_notRegistered_returnsNull() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getClientInflowThreshold("C1")).thenReturn(null);
|
||||
|
||||
assertNull(serviceWith(manager).getClientMetric("C1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetClientMetric_success_returnsTrueAndCallsManager() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getClientInflowThreshold("C1")).thenReturn(makeVO("C1"));
|
||||
|
||||
assertTrue(serviceWith(manager).resetClientMetric("C1"));
|
||||
verify(manager).resetClientMetrics("C1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetClientMetric_notRegistered_returnsFalse() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
when(manager.getClientInflowThreshold("C1")).thenReturn(null);
|
||||
|
||||
assertFalse(serviceWith(manager).resetClientMetric("C1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetAllClientMetrics_callsManager() {
|
||||
DualInflowControlManager manager = mock(DualInflowControlManager.class);
|
||||
serviceWith(manager).resetAllClientMetrics();
|
||||
verify(manager).resetAllClientMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user