test(integration): 添加集成回退服务的单元测试

- 验证缓存存在时返回缓存值的功能
- 测试无缓存时调用远程服务并缓存结果
- 验证远程调用失败且无缓存时抛出异常
- 测试清除单个缓存项功能
- 验证清除服务所有缓存项功能
- 测试获取缓存统计信息功能
- 验证并发请求时只调用一次远程服务的互斥锁机制
This commit is contained in:
2026-01-05 14:56:51 +08:00
parent eb9b781fd3
commit 010bac1091

View File

@@ -0,0 +1,151 @@
package com.ycwl.basic.integration.common.service;
import com.ycwl.basic.integration.common.config.IntegrationProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.jupiter.api.Assertions.*;
class IntegrationFallbackServiceTest {
private IntegrationFallbackService service;
@BeforeEach
void setUp() {
service = new IntegrationFallbackService(new IntegrationProperties());
}
@Test
void shouldReturnCachedValueWhenCacheExists() {
String serviceName = "zt-scenic";
String cacheKey = "k1";
// 第一次调用,缓存结果
service.executeWithFallback(serviceName, cacheKey, () -> "cached", String.class);
// 第二次调用,应直接返回缓存,不调用远程
AtomicInteger remoteCalls = new AtomicInteger();
String result = service.executeWithFallback(serviceName, cacheKey, () -> {
remoteCalls.incrementAndGet();
return "remote";
}, String.class);
assertEquals("cached", result);
assertEquals(0, remoteCalls.get());
}
@Test
void shouldCallRemoteWhenNoCacheAndCacheResult() {
String serviceName = "zt-scenic";
String cacheKey = "k2";
AtomicInteger remoteCalls = new AtomicInteger();
String result = service.executeWithFallback(serviceName, cacheKey, () -> {
remoteCalls.incrementAndGet();
return "remote";
}, String.class);
assertEquals("remote", result);
assertEquals(1, remoteCalls.get());
assertTrue(service.hasFallbackCache(serviceName, cacheKey));
}
@Test
void shouldThrowWhenRemoteFailsAndNoCache() {
String serviceName = "zt-scenic";
String cacheKey = "k3";
RuntimeException ex = assertThrows(RuntimeException.class, () ->
service.executeWithFallback(serviceName, cacheKey, () -> {
throw new RuntimeException("boom");
}, String.class)
);
assertEquals("boom", ex.getMessage());
}
@Test
void shouldClearCache() {
String serviceName = "zt-scenic";
String cacheKey = "k4";
service.executeWithFallback(serviceName, cacheKey, () -> "value", String.class);
assertTrue(service.hasFallbackCache(serviceName, cacheKey));
service.clearFallbackCache(serviceName, cacheKey);
assertFalse(service.hasFallbackCache(serviceName, cacheKey));
}
@Test
void shouldClearAllCache() {
String serviceName = "zt-scenic";
service.executeWithFallback(serviceName, "key1", () -> "v1", String.class);
service.executeWithFallback(serviceName, "key2", () -> "v2", String.class);
service.clearAllFallbackCache(serviceName);
assertFalse(service.hasFallbackCache(serviceName, "key1"));
assertFalse(service.hasFallbackCache(serviceName, "key2"));
}
@Test
void shouldGetStats() {
String serviceName = "zt-device";
service.executeWithFallback(serviceName, "d1", () -> "v1", String.class);
service.executeWithFallback(serviceName, "d2", () -> "v2", String.class);
IntegrationFallbackService.FallbackCacheStats stats = service.getFallbackCacheStats(serviceName);
assertEquals(serviceName, stats.getServiceName());
assertEquals(2, stats.getTotalCacheCount());
assertEquals(1, stats.getCacheTtlMinutes());
}
@Test
void shouldOnlyCallRemoteOnceWithConcurrentRequests() throws InterruptedException {
String serviceName = "zt-scenic";
String cacheKey = "concurrent-test";
int threadCount = 10;
AtomicInteger remoteCalls = new AtomicInteger();
CountDownLatch startLatch = new CountDownLatch(1);
CountDownLatch doneLatch = new CountDownLatch(threadCount);
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
// 启动多个线程同时请求
for (int i = 0; i < threadCount; i++) {
executor.submit(() -> {
try {
startLatch.await(); // 等待同时开始
service.executeWithFallback(serviceName, cacheKey, () -> {
remoteCalls.incrementAndGet();
try {
Thread.sleep(50); // 模拟远程调用耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "result";
}, String.class);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
doneLatch.countDown();
}
});
}
startLatch.countDown(); // 同时放行所有线程
doneLatch.await(); // 等待所有线程完成
executor.shutdown();
// 互斥锁生效:只有一个线程真正调用了远程
assertEquals(1, remoteCalls.get());
}
}