diff --git a/elink-online-common b/elink-online-common index 437961e..8900966 160000 --- a/elink-online-common +++ b/elink-online-common @@ -1 +1 @@ -Subproject commit 437961e7d518df958b2b3109bf19d0c8beec4b3f +Subproject commit 8900966d71dbde9ca8a09b5e97e5629c4fbe69fa diff --git a/src/main/java/com/eactive/eai/custom/inbound/processor/DJBRequestProcessor.java b/src/main/java/com/eactive/eai/custom/inbound/processor/DJBRequestProcessor.java new file mode 100644 index 0000000..d2f8759 --- /dev/null +++ b/src/main/java/com/eactive/eai/custom/inbound/processor/DJBRequestProcessor.java @@ -0,0 +1,81 @@ +package com.eactive.eai.custom.inbound.processor; + +import org.apache.commons.lang3.StringUtils; + +import com.eactive.eai.common.inflow.Bucket; +import com.eactive.eai.common.inflow.InflowTargetVO; +import com.eactive.eai.common.inflow.dual.ClientDualBucket; +import com.eactive.eai.common.inflow.dual.DualBucket; +import com.eactive.eai.common.inflow.dual.DualCustomBucket; +import com.eactive.eai.inbound.processor.RequestProcessor; + +/** + * 어댑터/인터페이스/클라이언트 유량제어 차단 시 어느 버킷(PER_SECOND/THRESHOLD)에서 + * 차단됐는지 에러 메시지에 포함하는 RequestProcessor 확장. + * + *
ClientDualInflowControlManager와 함께 사용: + *
+ * inflow.control.bucket.className=com.eactive.eai.common.inflow.dual.ClientDualInflowControlManager + *+ * + *
Spring Bean 등록 후 기존 RequestProcessor 대신 이 클래스를 어댑터에 설정한다. + */ +public class DJBRequestProcessor extends RequestProcessor { + + @Override + protected String checkClientInflow(Bucket bucket, String clientId) { + if (StringUtils.isBlank(clientId)) return null; + if (bucket instanceof ClientDualBucket) { + return ((ClientDualBucket) bucket).isClientPassDetail(clientId); + } + return null; + } + + @Override + protected InflowTargetVO resolveClientInflowThreshold(Bucket bucket, String clientId) { + if (bucket instanceof ClientDualBucket) { + return ((ClientDualBucket) bucket).getClientInflowThreshold(clientId); + } + return null; + } + + @Override + protected String checkAdapterInflow(Bucket bucket, String adapterGroupName) { + if (bucket instanceof DualBucket) { + return ((DualBucket) bucket).isAdapterPassDetail(adapterGroupName); + } + return super.checkAdapterInflow(bucket, adapterGroupName); + } + + @Override + protected String checkInterfaceInflow(Bucket bucket, String eaiSvcCd) { + if (bucket instanceof DualBucket) { + return ((DualBucket) bucket).isInterfacePassDetail(eaiSvcCd); + } + return super.checkInterfaceInflow(bucket, eaiSvcCd); + } + + /** + * 차단 원인에 따라 에러 메시지에 한도 정보를 포함. + *
RequestProcessor 클래스는 static 초기화 블록에서 EAIServerManager.getInstance()를 호출한다. + * @BeforeAll에서 mock ApplicationContext를 주입한 뒤 DJBRequestProcessor를 최초 로딩시킨다. + * + *
주의: DJBRequestProcessor를 필드 타입으로 선언하면 테스트 클래스 로딩 시 함께 로딩되어 + * @BeforeAll 실행 전에 NPE가 발생한다. 반드시 메서드 본문 내에서만 참조해야 한다. + */ +class DJBRequestProcessorTest { + + @BeforeAll + static void setupMockApplicationContext() { + ApplicationContext mockContext = mock(ApplicationContext.class); + EAIServerManager mockServerManager = mock(EAIServerManager.class); + when(mockContext.getBean(EAIServerManager.class)).thenReturn(mockServerManager); + when(mockServerManager.getLocalServerName()).thenReturn("TEST-SERVER"); + when(mockServerManager.getGroupInstId()).thenReturn("TEST-INST"); + + ReflectionTestUtils.setField(ApplicationContextProvider.class, "context", mockContext); + } + + private InflowTargetVO makeVO(String name, long perSec, long threshold, String unit) { + InflowTargetVO vo = new InflowTargetVO(); + vo.setName(name); + vo.setThresholdPerSecond(perSec); + vo.setThreshold(threshold); + vo.setThresholdTimeUnit(unit); + vo.setActivate(true); + return vo; + } + + // ------------------------------------------------------------------------- + // checkAdapterInflow + // ------------------------------------------------------------------------- + + @Test + void checkAdapterInflow_dualBucket_pass_returnsNull() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + DualBucket mockBucket = mock(DualBucket.class); + when(mockBucket.isAdapterPassDetail("ADAPTER_A")).thenReturn(null); + + assertNull(processor.checkAdapterInflow(mockBucket, "ADAPTER_A")); + verify(mockBucket).isAdapterPassDetail("ADAPTER_A"); + } + + @Test + void checkAdapterInflow_dualBucket_blockedPerSecond() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + DualBucket mockBucket = mock(DualBucket.class); + when(mockBucket.isAdapterPassDetail("ADAPTER_A")).thenReturn(DualCustomBucket.RESULT_BLOCKED_PER_SECOND); + + assertEquals(DualCustomBucket.RESULT_BLOCKED_PER_SECOND, + processor.checkAdapterInflow(mockBucket, "ADAPTER_A")); + } + + @Test + void checkAdapterInflow_dualBucket_blockedThreshold() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + DualBucket mockBucket = mock(DualBucket.class); + when(mockBucket.isAdapterPassDetail("ADAPTER_A")).thenReturn(DualCustomBucket.RESULT_BLOCKED_THRESHOLD); + + assertEquals(DualCustomBucket.RESULT_BLOCKED_THRESHOLD, + processor.checkAdapterInflow(mockBucket, "ADAPTER_A")); + } + + @Test + void checkAdapterInflow_nonDualBucket_pass_returnsNull() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + Bucket mockBucket = mock(Bucket.class); + when(mockBucket.isAdapterPass("ADAPTER_A")).thenReturn(true); + + assertNull(processor.checkAdapterInflow(mockBucket, "ADAPTER_A")); + } + + @Test + void checkAdapterInflow_nonDualBucket_blocked_returnsBlocked() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + Bucket mockBucket = mock(Bucket.class); + when(mockBucket.isAdapterPass("ADAPTER_A")).thenReturn(false); + + assertEquals("BLOCKED", processor.checkAdapterInflow(mockBucket, "ADAPTER_A")); + } + + // ------------------------------------------------------------------------- + // checkInterfaceInflow + // ------------------------------------------------------------------------- + + @Test + void checkInterfaceInflow_dualBucket_pass_returnsNull() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + DualBucket mockBucket = mock(DualBucket.class); + when(mockBucket.isInterfacePassDetail("IF_001")).thenReturn(null); + + assertNull(processor.checkInterfaceInflow(mockBucket, "IF_001")); + verify(mockBucket).isInterfacePassDetail("IF_001"); + } + + @Test + void checkInterfaceInflow_dualBucket_blockedPerSecond() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + DualBucket mockBucket = mock(DualBucket.class); + when(mockBucket.isInterfacePassDetail("IF_001")).thenReturn(DualCustomBucket.RESULT_BLOCKED_PER_SECOND); + + assertEquals(DualCustomBucket.RESULT_BLOCKED_PER_SECOND, + processor.checkInterfaceInflow(mockBucket, "IF_001")); + } + + @Test + void checkInterfaceInflow_nonDualBucket_pass_returnsNull() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + Bucket mockBucket = mock(Bucket.class); + when(mockBucket.isInterfacePass("IF_001")).thenReturn(true); + + assertNull(processor.checkInterfaceInflow(mockBucket, "IF_001")); + } + + @Test + void checkInterfaceInflow_nonDualBucket_blocked_returnsBlocked() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + Bucket mockBucket = mock(Bucket.class); + when(mockBucket.isInterfacePass("IF_001")).thenReturn(false); + + assertEquals("BLOCKED", processor.checkInterfaceInflow(mockBucket, "IF_001")); + } + + // ------------------------------------------------------------------------- + // checkClientInflow — ClientDualBucket 기반 + // ------------------------------------------------------------------------- + + @Test + void checkClientInflow_clientDualBucket_pass_returnsNull() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + ClientDualBucket mockBucket = mock(ClientDualBucket.class); + when(mockBucket.isClientPassDetail("CLIENT_A")).thenReturn(null); + + assertNull(processor.checkClientInflow(mockBucket, "CLIENT_A")); + verify(mockBucket).isClientPassDetail("CLIENT_A"); + } + + @Test + void checkClientInflow_clientDualBucket_blocked() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + ClientDualBucket mockBucket = mock(ClientDualBucket.class); + when(mockBucket.isClientPassDetail("CLIENT_A")).thenReturn(DualCustomBucket.RESULT_BLOCKED_THRESHOLD); + + assertEquals(DualCustomBucket.RESULT_BLOCKED_THRESHOLD, + processor.checkClientInflow(mockBucket, "CLIENT_A")); + } + + @Test + void checkClientInflow_nonClientDualBucket_returnsNull() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + Bucket mockBucket = mock(Bucket.class); + + assertNull(processor.checkClientInflow(mockBucket, "CLIENT_A")); + } + + @Test + void checkClientInflow_blankClientId_returnsNull() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + ClientDualBucket mockBucket = mock(ClientDualBucket.class); + + assertNull(processor.checkClientInflow(mockBucket, "")); + verify(mockBucket, never()).isClientPassDetail(any()); + } + + // ------------------------------------------------------------------------- + // buildInflowTargetErrorMsg + // ------------------------------------------------------------------------- + + @Test + void buildInflowTargetErrorMsg_perSecond_includesReqPerSec() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + InflowTargetVO vo = makeVO("결제API", 30, 1000, "MIN"); + + String msg = processor.buildInflowTargetErrorMsg(vo, DualCustomBucket.RESULT_BLOCKED_PER_SECOND); + + assertEquals("API 호출 한도 초과 [결제API: 30req/sec]", msg); + } + + @Test + void buildInflowTargetErrorMsg_threshold_includesReqPerUnit() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + InflowTargetVO vo = makeVO("결제API", 30, 1000, "MIN"); + + String msg = processor.buildInflowTargetErrorMsg(vo, DualCustomBucket.RESULT_BLOCKED_THRESHOLD); + + assertEquals("API 호출 한도 초과 [결제API: 1000req/MIN]", msg); + } + + @Test + void buildInflowTargetErrorMsg_blockedFallback_simpleFormat() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + InflowTargetVO vo = makeVO("결제API", 30, 1000, "MIN"); + + String msg = processor.buildInflowTargetErrorMsg(vo, "BLOCKED"); + + assertEquals("API 호출 한도 초과 [결제API]", msg); + } + + @Test + void buildInflowTargetErrorMsg_nullBlockedType_simpleFormat() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + InflowTargetVO vo = makeVO("결제API", 30, 1000, "MIN"); + + String msg = processor.buildInflowTargetErrorMsg(vo, null); + + assertEquals("API 호출 한도 초과 [결제API]", msg); + } + + @Test + void buildInflowTargetErrorMsg_hourUnit() { + DJBRequestProcessor processor = new DJBRequestProcessor(); + InflowTargetVO vo = makeVO("조회API", 10, 500, "HOUR"); + + String msg = processor.buildInflowTargetErrorMsg(vo, DualCustomBucket.RESULT_BLOCKED_THRESHOLD); + + assertEquals("API 호출 한도 초과 [조회API: 500req/HOUR]", msg); + } +} diff --git a/src/test/java/com/eactive/eai/custom/inflow/ClientInflowTargetMetricControllerTest.java b/src/test/java/com/eactive/eai/custom/inflow/ClientInflowTargetMetricControllerTest.java new file mode 100644 index 0000000..ce996b9 --- /dev/null +++ b/src/test/java/com/eactive/eai/custom/inflow/ClientInflowTargetMetricControllerTest.java @@ -0,0 +1,144 @@ +package com.eactive.eai.custom.inflow; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.http.ResponseEntity; +import org.springframework.test.util.ReflectionTestUtils; + +import com.eactive.eai.manage.inflow.TargetMetricDTO; + +/** + * ClientInflowTargetMetricController 단위 테스트. + * + *
Spring MVC를 기동하지 않고 컨트롤러를 직접 인스턴스화하여
+ * 응답 구조(success, data, count, message)를 검증한다.
+ */
+class ClientInflowTargetMetricControllerTest {
+
+ private ClientInflowTargetMetricController controller;
+ private ClientInflowTargetMetricService mockService;
+
+ @BeforeEach
+ void setUp() {
+ controller = new ClientInflowTargetMetricController();
+ mockService = mock(ClientInflowTargetMetricService.class);
+ ReflectionTestUtils.setField(controller, "metricService", mockService);
+ }
+
+ private TargetMetricDTO makeDTO(String targetId, String targetType,
+ long allowed, long rejPs, long rejTh) {
+ TargetMetricDTO dto = new TargetMetricDTO();
+ dto.setTargetId(targetId);
+ dto.setTargetType(targetType);
+ dto.setActivate(true);
+ dto.setAllowed(allowed);
+ dto.setRejectedPerSecond(rejPs);
+ dto.setRejectedThreshold(rejTh);
+ long total = allowed + rejPs + rejTh;
+ dto.setTotalRequests(total);
+ dto.setRejectRatio(total > 0 ? (double)(rejPs + rejTh) / total * 100 : 0.0);
+ return dto;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Map getDualManager()를 protected로 오버라이드하는 내부 테스트 서브클래스를 사용하여
- * DualInflowControlManager 의존성을 주입한다.
+ * 어댑터/인터페이스: 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 getDualManager()를 오버라이드하여 DualInflowControlManager 의존성을 주입한다.
+ * 어댑터/인터페이스 테스트는 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();
- }
}