refactor(cache): 缓存操作接口化,支持 Redis/Caffeine 双实现切换
将系统所有缓存操作从 `RedisUtil` 迁移至 `CacheOperations` 接口, 通过 `gym.cache.type` 配置选择 Redis 或 Caffeine 实现。 变更内容: - 新增 CacheOperations 接口,定义 get/set/delete/hasKey/expire/deleteByPattern 等标准方法 - 新增 RedisCacheOperations 实现(基于 ReactiveRedisTemplate,默认实现) - 新增 CaffeineCacheOperations 实现(基于 Caffeine 本地缓存) - 新增 CacheProperties 配置类,支持 Caffeine 容量/过期等参数配置 - 新增 CacheAutoConfiguration 自动装配,通过 AutoConfiguration.imports 注册 - 全系统 17 个业务服务 + 18 个测试文件从 RedisUtil 迁移至 CacheOperations - manage-gateway 配置 caffeine 实现(无需 Redis),manage-app 配置 redis 实现 - 分布式锁等 Redis 独有特性保持直接使用 ReactiveRedisTemplate 测试:202 通过,0 失败,0 错误
This commit was merged in pull request #56.
This commit is contained in:
+5
-5
@@ -2,7 +2,7 @@
|
||||
package cn.novalon.gym.manage.groupcourse.handler;
|
||||
|
||||
import cn.novalon.gym.manage.common.dto.PageRequest;
|
||||
import cn.novalon.gym.manage.common.util.RedisUtil;
|
||||
import cn.novalon.gym.manage.common.cache.CacheOperations;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseDetail;
|
||||
import cn.novalon.gym.manage.groupcourse.dto.GroupCourseQueryDto;
|
||||
@@ -30,16 +30,16 @@ public class GroupCourseHandler {
|
||||
private static final Logger logger = LoggerFactory.getLogger(GroupCourseHandler.class);
|
||||
private final IGroupCourseService groupCourseService;
|
||||
private final Validator validator;
|
||||
private final RedisUtil redisUtil;
|
||||
private final CacheOperations cacheOperations;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public GroupCourseHandler(IGroupCourseService groupCourseService,
|
||||
Validator validator,
|
||||
RedisUtil redisUtil,
|
||||
CacheOperations cacheOperations,
|
||||
ObjectMapper objectMapper){
|
||||
this.groupCourseService = groupCourseService;
|
||||
this.validator = validator;
|
||||
this.redisUtil = redisUtil;
|
||||
this.cacheOperations = cacheOperations;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ public class GroupCourseHandler {
|
||||
return ServerResponse.badRequest().bodyValue(error);
|
||||
}
|
||||
|
||||
return redisUtil.get(key)
|
||||
return cacheOperations.get(key)
|
||||
.map(cachedValue -> {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (cachedValue != null) {
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@ package cn.novalon.gym.manage.groupcourse.service.impl;
|
||||
|
||||
import cn.novalon.gym.manage.common.dto.PageRequest;
|
||||
import cn.novalon.gym.manage.common.dto.PageResponse;
|
||||
import cn.novalon.gym.manage.common.util.RedisUtil;
|
||||
import cn.novalon.gym.manage.common.cache.CacheOperations;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.CourseLabel;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
|
||||
import cn.novalon.gym.manage.groupcourse.repository.ICourseLabelRepository;
|
||||
@@ -24,21 +24,21 @@ public class CourseLabelService implements ICourseLabelService {
|
||||
|
||||
private final ICourseLabelRepository courseLabelRepository;
|
||||
private final IGroupCourseRepository groupCourseRepository;
|
||||
private final RedisUtil redisUtil;
|
||||
private final CacheOperations cacheOperations;
|
||||
|
||||
public CourseLabelService(ICourseLabelRepository courseLabelRepository,
|
||||
IGroupCourseRepository groupCourseRepository,
|
||||
RedisUtil redisUtil) {
|
||||
CacheOperations cacheOperations) {
|
||||
this.courseLabelRepository = courseLabelRepository;
|
||||
this.groupCourseRepository = groupCourseRepository;
|
||||
this.redisUtil = redisUtil;
|
||||
this.cacheOperations = cacheOperations;
|
||||
}
|
||||
|
||||
private Mono<Void> invalidateGroupCourseDetailCache(Long typeId) {
|
||||
return groupCourseRepository.findByCourseType(typeId)
|
||||
.flatMap(course -> {
|
||||
String cacheKey = CACHE_KEY_DETAIL_PREFIX + course.getId();
|
||||
return redisUtil.delete(cacheKey)
|
||||
return cacheOperations.delete(cacheKey)
|
||||
.doOnSuccess(deleted -> logger.debug("清除团课详情缓存 - courseId={}", course.getId()));
|
||||
})
|
||||
.then();
|
||||
|
||||
+24
-39
@@ -1,8 +1,7 @@
|
||||
package cn.novalon.gym.manage.groupcourse.service.impl;
|
||||
|
||||
import cn.novalon.gym.manage.common.cache.CacheOperations;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.redis.core.ReactiveRedisTemplate;
|
||||
@@ -13,9 +12,11 @@ import java.time.Duration;
|
||||
|
||||
/**
|
||||
* 团课Redis缓存服务
|
||||
*
|
||||
* 负责团课信息的缓存管理和分布式锁实现
|
||||
*
|
||||
* <p>
|
||||
* 缓存操作委托给 {@link CacheOperations} 接口,支持通过配置切换 Redis / Caffeine 实现。
|
||||
* 分布式锁操作仍直接使用 {@link ReactiveRedisTemplate}(锁为 Redis 独有特性)。
|
||||
* </p>
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-06-01
|
||||
*/
|
||||
@@ -33,13 +34,13 @@ public class GroupCourseRedisService {
|
||||
// 锁过期时间(30秒)
|
||||
private static final Duration LOCK_EXPIRE_TIME = Duration.ofSeconds(30);
|
||||
|
||||
private final CacheOperations cacheOperations;
|
||||
private final ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public GroupCourseRedisService(ReactiveRedisTemplate<String, Object> reactiveRedisTemplate,
|
||||
ObjectMapper objectMapper) {
|
||||
public GroupCourseRedisService(CacheOperations cacheOperations,
|
||||
ReactiveRedisTemplate<String, Object> reactiveRedisTemplate) {
|
||||
this.cacheOperations = cacheOperations;
|
||||
this.reactiveRedisTemplate = reactiveRedisTemplate;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,16 +62,9 @@ public class GroupCourseRedisService {
|
||||
*/
|
||||
public Mono<Void> cacheCourse(GroupCourse course) {
|
||||
String key = getCourseCacheKey(course.getId());
|
||||
try {
|
||||
String value = objectMapper.writeValueAsString(course);
|
||||
return reactiveRedisTemplate.opsForValue()
|
||||
.set(key, value, CACHE_EXPIRE_TIME)
|
||||
.doOnSuccess(result -> logger.debug("团课信息已缓存:courseId={}", course.getId()))
|
||||
.then();
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.error("序列化团课信息失败:courseId={}", course.getId(), e);
|
||||
return Mono.error(e);
|
||||
}
|
||||
return cacheOperations.setWithExpire(key, course, CACHE_EXPIRE_TIME.toSeconds())
|
||||
.doOnSuccess(result -> logger.debug("团课信息已缓存:courseId={}", course.getId()))
|
||||
.then();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,19 +72,8 @@ public class GroupCourseRedisService {
|
||||
*/
|
||||
public Mono<GroupCourse> getCachedCourse(Long courseId) {
|
||||
String key = getCourseCacheKey(courseId);
|
||||
return reactiveRedisTemplate.opsForValue()
|
||||
.get(key)
|
||||
.cast(String.class)
|
||||
.flatMap(value -> {
|
||||
try {
|
||||
GroupCourse course = objectMapper.readValue(value, GroupCourse.class);
|
||||
logger.debug("从缓存获取团课信息:courseId={}", courseId);
|
||||
return Mono.just(course);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.error("反序列化团课信息失败:courseId={}", courseId, e);
|
||||
return Mono.empty();
|
||||
}
|
||||
})
|
||||
return cacheOperations.get(key, GroupCourse.class)
|
||||
.doOnNext(course -> logger.debug("从缓存获取团课信息:courseId={}", courseId))
|
||||
.switchIfEmpty(Mono.fromRunnable(() -> logger.debug("缓存中未找到团课信息:courseId={}", courseId)));
|
||||
}
|
||||
|
||||
@@ -99,15 +82,16 @@ public class GroupCourseRedisService {
|
||||
*/
|
||||
public Mono<Void> invalidateCourseCache(Long courseId) {
|
||||
String key = getCourseCacheKey(courseId);
|
||||
return reactiveRedisTemplate.delete(key)
|
||||
return cacheOperations.delete(key)
|
||||
.doOnSuccess(result -> logger.debug("团课缓存已删除:courseId={}", courseId))
|
||||
.then();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分布式锁
|
||||
*
|
||||
* @param courseId 课程ID
|
||||
* <p>注意:分布式锁为 Redis 独有特性,始终保持直接使用 RedisTemplate。</p>
|
||||
*
|
||||
* @param courseId 课程ID
|
||||
* @param requestId 请求ID(用于锁的唯一性校验)
|
||||
* @return 是否获取成功
|
||||
*/
|
||||
@@ -126,8 +110,9 @@ public class GroupCourseRedisService {
|
||||
|
||||
/**
|
||||
* 释放分布式锁
|
||||
*
|
||||
* @param courseId 课程ID
|
||||
* <p>注意:分布式锁为 Redis 独有特性,始终保持直接使用 RedisTemplate。</p>
|
||||
*
|
||||
* @param courseId 课程ID
|
||||
* @param requestId 请求ID(用于锁的唯一性校验)
|
||||
* @return 是否释放成功
|
||||
*/
|
||||
@@ -142,11 +127,11 @@ public class GroupCourseRedisService {
|
||||
.map(deleted -> deleted > 0)
|
||||
.doOnSuccess(result -> logger.debug("释放预约锁成功:courseId={}, requestId={}", courseId, requestId));
|
||||
} else {
|
||||
logger.warn("锁归属校验失败:courseId={}, expectedRequestId={}, actualRequestId={}",
|
||||
logger.warn("锁归属校验失败:courseId={}, expectedRequestId={}, actualRequestId={}",
|
||||
courseId, requestId, storedRequestId);
|
||||
return Mono.just(false);
|
||||
}
|
||||
})
|
||||
.defaultIfEmpty(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
-17
@@ -1,9 +1,9 @@
|
||||
|
||||
package cn.novalon.gym.manage.groupcourse.service.impl;
|
||||
|
||||
import cn.novalon.gym.manage.common.cache.CacheOperations;
|
||||
import cn.novalon.gym.manage.common.dto.PageRequest;
|
||||
import cn.novalon.gym.manage.common.dto.PageResponse;
|
||||
import cn.novalon.gym.manage.common.util.RedisUtil;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.CourseLabel;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseBooking;
|
||||
@@ -53,7 +53,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
private final ICourseLabelRepository courseLabelRepository;
|
||||
private final IMemberCardRecordService memberCardRecordService;
|
||||
private final MemberCardRepository memberCardRepository;
|
||||
private final RedisUtil redisUtil;
|
||||
private final CacheOperations cacheOperations;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final GroupCourseStateMachine stateMachine;
|
||||
private final DatabaseClient databaseClient;
|
||||
@@ -73,7 +73,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
ICourseLabelRepository courseLabelRepository,
|
||||
IMemberCardRecordService memberCardRecordService,
|
||||
MemberCardRepository memberCardRepository,
|
||||
RedisUtil redisUtil,
|
||||
CacheOperations cacheOperations,
|
||||
ObjectMapper objectMapper,
|
||||
GroupCourseStateMachine stateMachine,
|
||||
DatabaseClient databaseClient,
|
||||
@@ -85,7 +85,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
this.courseLabelRepository = courseLabelRepository;
|
||||
this.memberCardRecordService = memberCardRecordService;
|
||||
this.memberCardRepository = memberCardRepository;
|
||||
this.redisUtil = redisUtil;
|
||||
this.cacheOperations = cacheOperations;
|
||||
this.objectMapper = objectMapper;
|
||||
this.stateMachine = stateMachine;
|
||||
this.databaseClient = databaseClient;
|
||||
@@ -97,7 +97,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
public Mono<GroupCourseDetail> findDetailById(Long id) {
|
||||
String cacheKey = CACHE_KEY_DETAIL_PREFIX + id;
|
||||
|
||||
Mono<String> cachedMono = redisUtil.get(cacheKey, String.class);
|
||||
Mono<String> cachedMono = cacheOperations.get(cacheKey, String.class);
|
||||
return cachedMono
|
||||
.flatMap(cachedJson -> {
|
||||
if (cachedJson != null && !cachedJson.isEmpty()) {
|
||||
@@ -107,7 +107,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
return Mono.<GroupCourseDetail>just(detail);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.warn("缓存解析失败,删除缓存 - id: {}, error: {}", id, e.getMessage());
|
||||
return redisUtil.delete(cacheKey).then(Mono.<GroupCourseDetail>empty());
|
||||
return cacheOperations.delete(cacheKey).then(Mono.<GroupCourseDetail>empty());
|
||||
}
|
||||
}
|
||||
return Mono.<GroupCourseDetail>empty();
|
||||
@@ -141,7 +141,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
.flatMap(detail -> {
|
||||
try {
|
||||
String jsonData = objectMapper.writeValueAsString(detail);
|
||||
return redisUtil.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS)
|
||||
return cacheOperations.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS)
|
||||
.thenReturn(detail)
|
||||
.doOnSuccess(d -> logger.debug("缓存已设置 - findDetailById: id={}", id));
|
||||
} catch (JsonProcessingException e) {
|
||||
@@ -233,7 +233,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
public Mono<GroupCourse> findById(Long id) {
|
||||
String cacheKey = CACHE_KEY_ID_PREFIX + id;
|
||||
|
||||
Mono<String> cachedMono = redisUtil.get(cacheKey, String.class);
|
||||
Mono<String> cachedMono = cacheOperations.get(cacheKey, String.class);
|
||||
return cachedMono
|
||||
.flatMap(cachedJson -> {
|
||||
if (cachedJson != null && !cachedJson.isEmpty()) {
|
||||
@@ -243,7 +243,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
return Mono.<GroupCourse>just(groupCourse);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.warn("缓存解析失败,删除缓存 - id: {}, error: {}", id, e.getMessage());
|
||||
return redisUtil.delete(cacheKey).then(Mono.<GroupCourse>empty());
|
||||
return cacheOperations.delete(cacheKey).then(Mono.<GroupCourse>empty());
|
||||
}
|
||||
}
|
||||
return Mono.<GroupCourse>empty();
|
||||
@@ -253,7 +253,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
.flatMap(groupCourse -> {
|
||||
try {
|
||||
String jsonData = objectMapper.writeValueAsString(groupCourse);
|
||||
return redisUtil.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS)
|
||||
return cacheOperations.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS)
|
||||
.thenReturn(groupCourse)
|
||||
.doOnSuccess(gc -> logger.debug("缓存已设置 - findById: id={}", id));
|
||||
} catch (JsonProcessingException e) {
|
||||
@@ -332,7 +332,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
|
||||
String cacheKey = CACHE_KEY_PREFIX + page + ":" + size + ":" + includeDeleted + ":" + sort + ":" + order + ":" + keyword + ":" + status;
|
||||
|
||||
Mono<String> cachedMono = redisUtil.get(cacheKey, String.class);
|
||||
Mono<String> cachedMono = cacheOperations.get(cacheKey, String.class);
|
||||
return cachedMono
|
||||
.flatMap(cachedJson -> {
|
||||
if (cachedJson != null && !cachedJson.isEmpty()) {
|
||||
@@ -343,7 +343,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
return Mono.<PageResponse<GroupCourse>>just(pageResponse);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.warn("缓存解析失败,删除缓存 - key: {}, error: {}", cacheKey, e.getMessage());
|
||||
return redisUtil.delete(cacheKey).then(Mono.<PageResponse<GroupCourse>>empty());
|
||||
return cacheOperations.delete(cacheKey).then(Mono.<PageResponse<GroupCourse>>empty());
|
||||
}
|
||||
}
|
||||
return Mono.<PageResponse<GroupCourse>>empty();
|
||||
@@ -361,7 +361,7 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
return resultMono.flatMap(pageResponse -> {
|
||||
try {
|
||||
String jsonData = objectMapper.writeValueAsString(pageResponse);
|
||||
return redisUtil.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS)
|
||||
return cacheOperations.setWithExpire(cacheKey, jsonData, CACHE_EXPIRE_SECONDS)
|
||||
.thenReturn(pageResponse)
|
||||
.doOnSuccess(pr -> logger.debug("缓存已设置 - findByPage: key={}", cacheKey));
|
||||
} catch (JsonProcessingException e) {
|
||||
@@ -739,10 +739,10 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
}
|
||||
|
||||
private Mono<Void> clearCache() {
|
||||
return redisUtil.deleteByPattern(CACHE_KEY_PREFIX + "*")
|
||||
.then(redisUtil.deleteByPattern(CACHE_KEY_ID_PREFIX + "*"))
|
||||
.then(redisUtil.deleteByPattern(CACHE_KEY_DETAIL_PREFIX + "*"))
|
||||
.then(redisUtil.deleteByPattern("datacount:statistics:*"))
|
||||
return cacheOperations.deleteByPattern(CACHE_KEY_PREFIX + "*")
|
||||
.then(cacheOperations.deleteByPattern(CACHE_KEY_ID_PREFIX + "*"))
|
||||
.then(cacheOperations.deleteByPattern(CACHE_KEY_DETAIL_PREFIX + "*"))
|
||||
.then(cacheOperations.deleteByPattern("datacount:statistics:*"))
|
||||
.then();
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package cn.novalon.gym.manage.groupcourse.handler;
|
||||
|
||||
import cn.novalon.gym.manage.common.util.RedisUtil;
|
||||
import cn.novalon.gym.manage.common.cache.CacheOperations;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseDetail;
|
||||
import cn.novalon.gym.manage.groupcourse.service.IGroupCourseService;
|
||||
@@ -35,7 +35,7 @@ class GroupCourseHandlerTest {
|
||||
private Validator validator;
|
||||
|
||||
@Mock
|
||||
private RedisUtil redisUtil;
|
||||
private CacheOperations cacheOperations;
|
||||
|
||||
@Mock
|
||||
private ObjectMapper objectMapper;
|
||||
@@ -44,7 +44,7 @@ class GroupCourseHandlerTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
handler = new GroupCourseHandler(groupCourseService, validator, redisUtil, objectMapper);
|
||||
handler = new GroupCourseHandler(groupCourseService, validator, cacheOperations, objectMapper);
|
||||
}
|
||||
|
||||
// ==================== getAllGroupCourse ====================
|
||||
|
||||
+16
-16
@@ -2,7 +2,7 @@ package cn.novalon.gym.manage.groupcourse.service.impl;
|
||||
|
||||
import cn.novalon.gym.manage.common.dto.PageRequest;
|
||||
import cn.novalon.gym.manage.common.dto.PageResponse;
|
||||
import cn.novalon.gym.manage.common.util.RedisUtil;
|
||||
import cn.novalon.gym.manage.common.cache.CacheOperations;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.CourseLabel;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
|
||||
import cn.novalon.gym.manage.groupcourse.repository.ICourseLabelRepository;
|
||||
@@ -38,13 +38,13 @@ class CourseLabelServiceTest {
|
||||
private IGroupCourseRepository groupCourseRepository;
|
||||
|
||||
@Mock
|
||||
private RedisUtil redisUtil;
|
||||
private CacheOperations cacheOperations;
|
||||
|
||||
private CourseLabelService courseLabelService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
courseLabelService = new CourseLabelService(courseLabelRepository, groupCourseRepository, redisUtil);
|
||||
courseLabelService = new CourseLabelService(courseLabelRepository, groupCourseRepository, cacheOperations);
|
||||
}
|
||||
|
||||
// ==================== findById ====================
|
||||
@@ -287,16 +287,16 @@ class CourseLabelServiceTest {
|
||||
GroupCourse course2 = new GroupCourse();
|
||||
course2.setId(102L);
|
||||
when(groupCourseRepository.findByCourseType(1L)).thenReturn(Flux.just(course1, course2));
|
||||
when(redisUtil.delete("group_course:detail:101")).thenReturn(Mono.just(1L));
|
||||
when(redisUtil.delete("group_course:detail:102")).thenReturn(Mono.just(1L));
|
||||
when(cacheOperations.delete("group_course:detail:101")).thenReturn(Mono.just(1L));
|
||||
when(cacheOperations.delete("group_course:detail:102")).thenReturn(Mono.just(1L));
|
||||
|
||||
StepVerifier.create(courseLabelService.addLabelsToType(1L, List.of(1L, 2L)))
|
||||
.verifyComplete();
|
||||
|
||||
verify(courseLabelRepository).addLabelsToType(1L, List.of(1L, 2L));
|
||||
verify(groupCourseRepository).findByCourseType(1L);
|
||||
verify(redisUtil).delete("group_course:detail:101");
|
||||
verify(redisUtil).delete("group_course:detail:102");
|
||||
verify(cacheOperations).delete("group_course:detail:101");
|
||||
verify(cacheOperations).delete("group_course:detail:102");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -309,7 +309,7 @@ class CourseLabelServiceTest {
|
||||
|
||||
verify(courseLabelRepository).addLabelsToType(1L, List.of(1L));
|
||||
verify(groupCourseRepository).findByCourseType(1L);
|
||||
verify(redisUtil, never()).delete(anyString());
|
||||
verify(cacheOperations, never()).delete(anyString());
|
||||
}
|
||||
|
||||
// ==================== removeLabelFromType ====================
|
||||
@@ -321,14 +321,14 @@ class CourseLabelServiceTest {
|
||||
GroupCourse course = new GroupCourse();
|
||||
course.setId(101L);
|
||||
when(groupCourseRepository.findByCourseType(1L)).thenReturn(Flux.just(course));
|
||||
when(redisUtil.delete("group_course:detail:101")).thenReturn(Mono.just(1L));
|
||||
when(cacheOperations.delete("group_course:detail:101")).thenReturn(Mono.just(1L));
|
||||
|
||||
StepVerifier.create(courseLabelService.removeLabelFromType(1L, 1L))
|
||||
.verifyComplete();
|
||||
|
||||
verify(courseLabelRepository).removeLabelFromType(1L, 1L);
|
||||
verify(groupCourseRepository).findByCourseType(1L);
|
||||
verify(redisUtil).delete("group_course:detail:101");
|
||||
verify(cacheOperations).delete("group_course:detail:101");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -340,7 +340,7 @@ class CourseLabelServiceTest {
|
||||
.verifyComplete();
|
||||
|
||||
verify(courseLabelRepository).removeLabelFromType(1L, 1L);
|
||||
verify(redisUtil, never()).delete(anyString());
|
||||
verify(cacheOperations, never()).delete(anyString());
|
||||
}
|
||||
|
||||
// ==================== clearLabelsFromType ====================
|
||||
@@ -354,16 +354,16 @@ class CourseLabelServiceTest {
|
||||
GroupCourse course2 = new GroupCourse();
|
||||
course2.setId(102L);
|
||||
when(groupCourseRepository.findByCourseType(1L)).thenReturn(Flux.just(course1, course2));
|
||||
when(redisUtil.delete("group_course:detail:101")).thenReturn(Mono.just(1L));
|
||||
when(redisUtil.delete("group_course:detail:102")).thenReturn(Mono.just(1L));
|
||||
when(cacheOperations.delete("group_course:detail:101")).thenReturn(Mono.just(1L));
|
||||
when(cacheOperations.delete("group_course:detail:102")).thenReturn(Mono.just(1L));
|
||||
|
||||
StepVerifier.create(courseLabelService.clearLabelsFromType(1L))
|
||||
.verifyComplete();
|
||||
|
||||
verify(courseLabelRepository).clearLabelsFromType(1L);
|
||||
verify(groupCourseRepository).findByCourseType(1L);
|
||||
verify(redisUtil).delete("group_course:detail:101");
|
||||
verify(redisUtil).delete("group_course:detail:102");
|
||||
verify(cacheOperations).delete("group_course:detail:101");
|
||||
verify(cacheOperations).delete("group_course:detail:102");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -375,7 +375,7 @@ class CourseLabelServiceTest {
|
||||
.verifyComplete();
|
||||
|
||||
verify(courseLabelRepository).clearLabelsFromType(1L);
|
||||
verify(redisUtil, never()).delete(anyString());
|
||||
verify(cacheOperations, never()).delete(anyString());
|
||||
}
|
||||
|
||||
// ==================== findByPage ====================
|
||||
|
||||
+19
-26
@@ -1,7 +1,7 @@
|
||||
package cn.novalon.gym.manage.groupcourse.service.impl;
|
||||
|
||||
import cn.novalon.gym.manage.common.cache.CacheOperations;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -21,14 +21,15 @@ import static org.mockito.Mockito.*;
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class GroupCourseRedisServiceTest {
|
||||
|
||||
@Mock
|
||||
private CacheOperations cacheOperations;
|
||||
|
||||
@Mock
|
||||
private ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;
|
||||
|
||||
@Mock
|
||||
private ReactiveValueOperations<String, Object> reactiveValueOps;
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private GroupCourseRedisService service;
|
||||
|
||||
private GroupCourse testCourse;
|
||||
@@ -36,7 +37,7 @@ class GroupCourseRedisServiceTest {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
lenient().when(reactiveRedisTemplate.opsForValue()).thenReturn(reactiveValueOps);
|
||||
service = new GroupCourseRedisService(reactiveRedisTemplate, objectMapper);
|
||||
service = new GroupCourseRedisService(cacheOperations, reactiveRedisTemplate);
|
||||
|
||||
testCourse = new GroupCourse();
|
||||
testCourse.setId(1L);
|
||||
@@ -47,20 +48,20 @@ class GroupCourseRedisServiceTest {
|
||||
// ==================== cacheCourse ====================
|
||||
|
||||
@Test
|
||||
void cacheCourse_shouldSerializeAndSetInRedis() {
|
||||
when(reactiveValueOps.set(eq("group_course:1"), anyString(), eq(Duration.ofMinutes(5))))
|
||||
void cacheCourse_shouldSetInCache() {
|
||||
when(cacheOperations.setWithExpire(eq("group_course:1"), eq(testCourse), eq(300L)))
|
||||
.thenReturn(Mono.just(true));
|
||||
|
||||
StepVerifier.create(service.cacheCourse(testCourse))
|
||||
.verifyComplete();
|
||||
|
||||
verify(reactiveValueOps).set(eq("group_course:1"), anyString(), eq(Duration.ofMinutes(5)));
|
||||
verify(cacheOperations).setWithExpire(eq("group_course:1"), eq(testCourse), eq(300L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void cacheCourse_shouldErrorWhenRedisFails() {
|
||||
when(reactiveValueOps.set(eq("group_course:1"), anyString(), eq(Duration.ofMinutes(5))))
|
||||
.thenReturn(Mono.error(new RuntimeException("Redis error")));
|
||||
void cacheCourse_shouldErrorWhenCacheFails() {
|
||||
when(cacheOperations.setWithExpire(eq("group_course:1"), eq(testCourse), eq(300L)))
|
||||
.thenReturn(Mono.error(new RuntimeException("Cache error")));
|
||||
|
||||
StepVerifier.create(service.cacheCourse(testCourse))
|
||||
.expectError(RuntimeException.class)
|
||||
@@ -70,9 +71,9 @@ class GroupCourseRedisServiceTest {
|
||||
// ==================== getCachedCourse ====================
|
||||
|
||||
@Test
|
||||
void getCachedCourse_shouldReturnCachedCourseWhenFound() throws Exception {
|
||||
String json = objectMapper.writeValueAsString(testCourse);
|
||||
when(reactiveValueOps.get("group_course:1")).thenReturn(Mono.just(json));
|
||||
void getCachedCourse_shouldReturnCachedCourseWhenFound() {
|
||||
when(cacheOperations.get(eq("group_course:1"), eq(GroupCourse.class)))
|
||||
.thenReturn(Mono.just(testCourse));
|
||||
|
||||
StepVerifier.create(service.getCachedCourse(1L))
|
||||
.assertNext(course -> {
|
||||
@@ -84,16 +85,8 @@ class GroupCourseRedisServiceTest {
|
||||
|
||||
@Test
|
||||
void getCachedCourse_shouldReturnEmptyWhenCacheMiss() {
|
||||
when(reactiveValueOps.get("group_course:1")).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(service.getCachedCourse(1L))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCachedCourse_shouldReturnEmptyWhenDeserializationFails() {
|
||||
String invalidJson = "invalid json";
|
||||
when(reactiveValueOps.get("group_course:1")).thenReturn(Mono.just(invalidJson));
|
||||
when(cacheOperations.get(eq("group_course:1"), eq(GroupCourse.class)))
|
||||
.thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(service.getCachedCourse(1L))
|
||||
.verifyComplete();
|
||||
@@ -102,13 +95,13 @@ class GroupCourseRedisServiceTest {
|
||||
// ==================== invalidateCourseCache ====================
|
||||
|
||||
@Test
|
||||
void invalidateCourseCache_shouldDeleteFromRedis() {
|
||||
when(reactiveRedisTemplate.delete("group_course:1")).thenReturn(Mono.just(1L));
|
||||
void invalidateCourseCache_shouldDeleteFromCache() {
|
||||
when(cacheOperations.delete("group_course:1")).thenReturn(Mono.just(1L));
|
||||
|
||||
StepVerifier.create(service.invalidateCourseCache(1L))
|
||||
.verifyComplete();
|
||||
|
||||
verify(reactiveRedisTemplate).delete("group_course:1");
|
||||
verify(cacheOperations).delete("group_course:1");
|
||||
}
|
||||
|
||||
// ==================== acquireLock ====================
|
||||
|
||||
+31
-31
@@ -2,7 +2,7 @@ package cn.novalon.gym.manage.groupcourse.service.impl;
|
||||
|
||||
import cn.novalon.gym.manage.common.dto.PageRequest;
|
||||
import cn.novalon.gym.manage.common.dto.PageResponse;
|
||||
import cn.novalon.gym.manage.common.util.RedisUtil;
|
||||
import cn.novalon.gym.manage.common.cache.CacheOperations;
|
||||
import cn.novalon.gym.manage.file.core.domain.SysFile;
|
||||
import cn.novalon.gym.manage.file.core.service.ISysFileService;
|
||||
import cn.novalon.gym.manage.groupcourse.domain.CourseLabel;
|
||||
@@ -63,7 +63,7 @@ class GroupCourseServiceTest {
|
||||
@Mock
|
||||
private MemberCardRepository memberCardRepository;
|
||||
@Mock
|
||||
private RedisUtil redisUtil;
|
||||
private CacheOperations cacheOperations;
|
||||
@Mock
|
||||
private GroupCourseStateMachine stateMachine;
|
||||
@Mock
|
||||
@@ -90,7 +90,7 @@ class GroupCourseServiceTest {
|
||||
groupCourseService = new GroupCourseService(
|
||||
groupCourseRepository, bookingRepository, groupCourseTypeRepository,
|
||||
courseLabelRepository, memberCardRecordService, memberCardRepository,
|
||||
redisUtil, objectMapper, stateMachine, databaseClient, fileService, sysUserRepository
|
||||
cacheOperations, objectMapper, stateMachine, databaseClient, fileService, sysUserRepository
|
||||
);
|
||||
|
||||
testCourse = new GroupCourse();
|
||||
@@ -136,10 +136,10 @@ class GroupCourseServiceTest {
|
||||
}
|
||||
|
||||
private void mockClearCache() {
|
||||
when(redisUtil.deleteByPattern("group_course:page:*")).thenReturn(Mono.just(0L));
|
||||
when(redisUtil.deleteByPattern("group_course:id:*")).thenReturn(Mono.just(0L));
|
||||
when(redisUtil.deleteByPattern("group_course:detail:*")).thenReturn(Mono.just(0L));
|
||||
when(redisUtil.deleteByPattern("datacount:statistics:*")).thenReturn(Mono.just(0L));
|
||||
when(cacheOperations.deleteByPattern("group_course:page:*")).thenReturn(Mono.just(0L));
|
||||
when(cacheOperations.deleteByPattern("group_course:id:*")).thenReturn(Mono.just(0L));
|
||||
when(cacheOperations.deleteByPattern("group_course:detail:*")).thenReturn(Mono.just(0L));
|
||||
when(cacheOperations.deleteByPattern("datacount:statistics:*")).thenReturn(Mono.just(0L));
|
||||
}
|
||||
|
||||
private void mockEnrichCurrentMembers() {
|
||||
@@ -157,7 +157,7 @@ class GroupCourseServiceTest {
|
||||
detail.setCoachName("张教练");
|
||||
String json = objectMapper.writeValueAsString(detail);
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.just(json));
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.just(json));
|
||||
// switchIfEmpty 的 Mono 参数被急切求值,需要 mock 以避免 NPE
|
||||
when(groupCourseRepository.findByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.empty());
|
||||
|
||||
@@ -169,7 +169,7 @@ class GroupCourseServiceTest {
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
verify(redisUtil).get(cacheKey, String.class);
|
||||
verify(cacheOperations).get(cacheKey, String.class);
|
||||
// switchIfEmpty 的 Mono 参数被急切求值,findByIdAndDeletedAtIsNull 会被调用但不会订阅
|
||||
}
|
||||
|
||||
@@ -177,13 +177,13 @@ class GroupCourseServiceTest {
|
||||
void findDetailById_cacheMissWithType_shouldBuildAndCacheDetail() throws Exception {
|
||||
String cacheKey = "group_course:detail:1";
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(groupCourseRepository.findByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.just(testCourse));
|
||||
when(groupCourseTypeRepository.findById(100L)).thenReturn(Mono.just(testType));
|
||||
when(courseLabelRepository.findByTypeId(100L)).thenReturn(Flux.just(testLabel));
|
||||
when(sysUserRepository.findByIdIncludingDeleted(10L)).thenReturn(Mono.just(testCoach));
|
||||
when(bookingRepository.countValidBookings(1L)).thenReturn(Mono.just(8L));
|
||||
when(redisUtil.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
when(cacheOperations.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
|
||||
StepVerifier.create(groupCourseService.findDetailById(1L))
|
||||
.assertNext(result -> {
|
||||
@@ -198,13 +198,13 @@ class GroupCourseServiceTest {
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
verify(redisUtil).get(cacheKey, String.class);
|
||||
verify(cacheOperations).get(cacheKey, String.class);
|
||||
verify(groupCourseRepository).findByIdAndDeletedAtIsNull(1L);
|
||||
verify(groupCourseTypeRepository).findById(100L);
|
||||
verify(courseLabelRepository).findByTypeId(100L);
|
||||
verify(sysUserRepository).findByIdIncludingDeleted(10L);
|
||||
verify(bookingRepository).countValidBookings(1L);
|
||||
verify(redisUtil).setWithExpire(eq(cacheKey), anyString(), eq(300L));
|
||||
verify(cacheOperations).setWithExpire(eq(cacheKey), anyString(), eq(300L));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -212,11 +212,11 @@ class GroupCourseServiceTest {
|
||||
String cacheKey = "group_course:detail:1";
|
||||
testCourse.setCourseType(null);
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(groupCourseRepository.findByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.just(testCourse));
|
||||
when(sysUserRepository.findByIdIncludingDeleted(10L)).thenReturn(Mono.just(testCoach));
|
||||
when(bookingRepository.countValidBookings(1L)).thenReturn(Mono.just(3L));
|
||||
when(redisUtil.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
when(cacheOperations.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
|
||||
StepVerifier.create(groupCourseService.findDetailById(1L))
|
||||
.assertNext(result -> {
|
||||
@@ -236,7 +236,7 @@ class GroupCourseServiceTest {
|
||||
void findDetailById_cacheMissNotFound_shouldReturnEmpty() {
|
||||
String cacheKey = "group_course:detail:1";
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(groupCourseRepository.findByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(groupCourseService.findDetailById(1L))
|
||||
@@ -250,15 +250,15 @@ class GroupCourseServiceTest {
|
||||
void findDetailById_cacheParseError_shouldDeleteCacheAndFallback() throws Exception {
|
||||
String cacheKey = "group_course:detail:1";
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.just("invalid-json"));
|
||||
when(redisUtil.delete(cacheKey)).thenReturn(Mono.just(1L));
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.just("invalid-json"));
|
||||
when(cacheOperations.delete(cacheKey)).thenReturn(Mono.just(1L));
|
||||
// After cache delete, switchIfEmpty kicks in
|
||||
when(groupCourseRepository.findByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.just(testCourse));
|
||||
when(groupCourseTypeRepository.findById(100L)).thenReturn(Mono.just(testType));
|
||||
when(courseLabelRepository.findByTypeId(100L)).thenReturn(Flux.just(testLabel));
|
||||
when(sysUserRepository.findByIdIncludingDeleted(10L)).thenReturn(Mono.just(testCoach));
|
||||
when(bookingRepository.countValidBookings(1L)).thenReturn(Mono.just(5L));
|
||||
when(redisUtil.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
when(cacheOperations.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
|
||||
StepVerifier.create(groupCourseService.findDetailById(1L))
|
||||
.assertNext(result -> {
|
||||
@@ -267,7 +267,7 @@ class GroupCourseServiceTest {
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
verify(redisUtil).delete(cacheKey);
|
||||
verify(cacheOperations).delete(cacheKey);
|
||||
verify(groupCourseRepository).findByIdAndDeletedAtIsNull(1L);
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ class GroupCourseServiceTest {
|
||||
String cacheKey = "group_course:id:1";
|
||||
String json = objectMapper.writeValueAsString(testCourse);
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.just(json));
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.just(json));
|
||||
// switchIfEmpty 的 Mono 参数被急切求值,需要 mock 以避免 NPE
|
||||
when(groupCourseRepository.findByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.empty());
|
||||
when(bookingRepository.countValidBookings(1L)).thenReturn(Mono.just(5L));
|
||||
@@ -290,7 +290,7 @@ class GroupCourseServiceTest {
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
verify(redisUtil).get(cacheKey, String.class);
|
||||
verify(cacheOperations).get(cacheKey, String.class);
|
||||
verify(bookingRepository).countValidBookings(1L);
|
||||
// switchIfEmpty 的 Mono 参数被急切求值,findByIdAndDeletedAtIsNull 会被调用但不会订阅
|
||||
}
|
||||
@@ -299,9 +299,9 @@ class GroupCourseServiceTest {
|
||||
void findById_cacheMiss_shouldQueryDbAndCache() throws Exception {
|
||||
String cacheKey = "group_course:id:1";
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(groupCourseRepository.findByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.just(testCourse));
|
||||
when(redisUtil.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
when(cacheOperations.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
when(bookingRepository.countValidBookings(1L)).thenReturn(Mono.just(5L));
|
||||
|
||||
StepVerifier.create(groupCourseService.findById(1L))
|
||||
@@ -312,7 +312,7 @@ class GroupCourseServiceTest {
|
||||
.verifyComplete();
|
||||
|
||||
verify(groupCourseRepository).findByIdAndDeletedAtIsNull(1L);
|
||||
verify(redisUtil).setWithExpire(eq(cacheKey), anyString(), eq(300L));
|
||||
verify(cacheOperations).setWithExpire(eq(cacheKey), anyString(), eq(300L));
|
||||
verify(bookingRepository).countValidBookings(1L);
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ class GroupCourseServiceTest {
|
||||
void findById_cacheMissNotFound_shouldReturnEmpty() {
|
||||
String cacheKey = "group_course:id:1";
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(groupCourseRepository.findByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.empty());
|
||||
|
||||
StepVerifier.create(groupCourseService.findById(1L))
|
||||
@@ -383,7 +383,7 @@ class GroupCourseServiceTest {
|
||||
String cacheKey = "group_course:page:0:10:false:id:asc::";
|
||||
String json = objectMapper.writeValueAsString(pageResponse);
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.just(json));
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.just(json));
|
||||
|
||||
StepVerifier.create(groupCourseService.findByPage(pageRequest, false))
|
||||
.assertNext(result -> {
|
||||
@@ -393,7 +393,7 @@ class GroupCourseServiceTest {
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
verify(redisUtil).get(cacheKey, String.class);
|
||||
verify(cacheOperations).get(cacheKey, String.class);
|
||||
verifyNoInteractions(groupCourseRepository);
|
||||
}
|
||||
|
||||
@@ -409,9 +409,9 @@ class GroupCourseServiceTest {
|
||||
|
||||
String cacheKey = "group_course:page:0:10:false:id:asc::";
|
||||
|
||||
when(redisUtil.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(cacheOperations.get(cacheKey, String.class)).thenReturn(Mono.empty());
|
||||
when(groupCourseRepository.findByPageAndNotDeleted(pageRequest)).thenReturn(Mono.just(pageResponse));
|
||||
when(redisUtil.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
when(cacheOperations.setWithExpire(eq(cacheKey), anyString(), eq(300L))).thenReturn(Mono.just(true));
|
||||
|
||||
StepVerifier.create(groupCourseService.findByPage(pageRequest, false))
|
||||
.assertNext(result -> {
|
||||
@@ -421,7 +421,7 @@ class GroupCourseServiceTest {
|
||||
.verifyComplete();
|
||||
|
||||
verify(groupCourseRepository).findByPageAndNotDeleted(pageRequest);
|
||||
verify(redisUtil).setWithExpire(eq(cacheKey), anyString(), eq(300L));
|
||||
verify(cacheOperations).setWithExpire(eq(cacheKey), anyString(), eq(300L));
|
||||
}
|
||||
|
||||
// ==================== create ====================
|
||||
|
||||
Reference in New Issue
Block a user