├── .gitignore ├── .idea ├── compiler.xml ├── encodings.xml ├── misc.xml └── vcs.xml ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── vincent │ │ └── demo │ │ ├── Application.java │ │ ├── config │ │ └── CacheConfig.java │ │ ├── log │ │ ├── QueryHistory.java │ │ └── QueryHistoryService.java │ │ ├── model │ │ ├── LikePO.java │ │ ├── PostPO.java │ │ ├── PostVO.java │ │ └── UserPO.java │ │ └── service │ │ ├── LikeService.java │ │ ├── PostService.java │ │ └── UserService.java └── resources │ └── application.properties └── test ├── java └── com │ └── vincent │ └── demo │ └── CacheTests.java └── resources └── application.properties /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | /.idea 3 | /target -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.1.2 9 | 10 | 11 | com.vincent 12 | demo 13 | 0.0.1-SNAPSHOT 14 | demo 15 | Demo project for Spring Boot 16 | 17 | 17 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-test 28 | test 29 | 30 | 31 | 32 | junit 33 | junit 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-data-redis 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-maven-plugin 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/Application.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | public class Application { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(Application.class, args); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/config/CacheConfig.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.config; 2 | 3 | import org.springframework.cache.CacheManager; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.data.redis.cache.RedisCacheConfiguration; 7 | import org.springframework.data.redis.cache.RedisCacheManager; 8 | import org.springframework.data.redis.connection.RedisConnectionFactory; 9 | import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; 10 | import org.springframework.data.redis.serializer.RedisSerializationContext; 11 | 12 | import java.time.Duration; 13 | 14 | @Configuration 15 | public class CacheConfig { 16 | 17 | @Bean 18 | public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory) { 19 | var serializer = new GenericJackson2JsonRedisSerializer(); 20 | var config = RedisCacheConfiguration.defaultCacheConfig() 21 | .entryTtl(Duration.ofMinutes(10)) 22 | .serializeValuesWith( 23 | RedisSerializationContext.SerializationPair.fromSerializer( 24 | serializer)); 25 | return RedisCacheManager.builder(connectionFactory) 26 | .cacheDefaults(config) 27 | .build(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/log/QueryHistory.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.log; 2 | 3 | public class QueryHistory { 4 | private String type; 5 | private String identifier; 6 | 7 | public static QueryHistory of(String type, String identifier) { 8 | var history = new QueryHistory(); 9 | history.type = type; 10 | history.identifier = identifier; 11 | return history; 12 | } 13 | 14 | public String getType() { 15 | return type; 16 | } 17 | 18 | public String getIdentifier() { 19 | return identifier; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/log/QueryHistoryService.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.log; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Service 9 | public class QueryHistoryService { 10 | private final List histories = new ArrayList<>(); 11 | 12 | public void add(String type, String identifier) { 13 | histories.add(QueryHistory.of(type, identifier)); 14 | } 15 | 16 | public boolean contains(String type, String identifier) { 17 | return histories.stream() 18 | .anyMatch(x -> x.getType().equals(type) && x.getIdentifier().equals(identifier)); 19 | } 20 | 21 | public void deleteAll() { 22 | histories.clear(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/model/LikePO.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.model; 2 | 3 | import java.util.Objects; 4 | 5 | public class LikePO { 6 | private String userId; 7 | private String postId; 8 | 9 | public static LikePO of(String userId, String postId) { 10 | var like = new LikePO(); 11 | like.userId = userId; 12 | like.postId = postId; 13 | 14 | return like; 15 | } 16 | 17 | public String getUserId() { 18 | return userId; 19 | } 20 | 21 | public String getPostId() { 22 | return postId; 23 | } 24 | 25 | @Override 26 | public int hashCode() { 27 | return Objects.hash(userId, postId); 28 | } 29 | 30 | @Override 31 | public boolean equals(Object o) { 32 | if (this == o) return true; 33 | if (o == null || getClass() != o.getClass()) return false; 34 | 35 | var other = (LikePO) o; 36 | return Objects.equals(userId, other.getUserId()) && 37 | Objects.equals(postId, other.getPostId()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/model/PostPO.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.model; 2 | 3 | public class PostPO { 4 | private String id; 5 | private String creatorId; 6 | private String title; 7 | 8 | public static PostPO of(String id, String creatorId, String title) { 9 | var post = new PostPO(); 10 | post.id = id; 11 | post.creatorId = creatorId; 12 | post.title = title; 13 | 14 | return post; 15 | } 16 | 17 | public String getId() { 18 | return id; 19 | } 20 | 21 | public String getCreatorId() { 22 | return creatorId; 23 | } 24 | 25 | public String getTitle() { 26 | return title; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/model/PostVO.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.model; 2 | 3 | import java.util.List; 4 | 5 | public class PostVO { 6 | private String id; 7 | private String creatorId; 8 | private String title; 9 | private String creatorName; 10 | private List likerNames; 11 | 12 | public static PostVO of(PostPO postPO, String creatorName, List likerNames) { 13 | var postVO = new PostVO(); 14 | postVO.id = postPO.getId(); 15 | postVO.creatorId = postPO.getCreatorId(); 16 | postVO.title = postPO.getTitle(); 17 | postVO.creatorName = creatorName; 18 | postVO.likerNames = likerNames; 19 | 20 | return postVO; 21 | } 22 | 23 | public String getId() { 24 | return id; 25 | } 26 | 27 | public String getCreatorId() { 28 | return creatorId; 29 | } 30 | 31 | public String getTitle() { 32 | return title; 33 | } 34 | 35 | public String getCreatorName() { 36 | return creatorName; 37 | } 38 | 39 | public List getLikerNames() { 40 | return likerNames; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/model/UserPO.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.model; 2 | 3 | import java.util.Date; 4 | 5 | public class UserPO { 6 | private String id; 7 | private String name; 8 | private Date createTime; 9 | 10 | public static UserPO of(String id, String name) { 11 | var user = new UserPO(); 12 | user.id = id; 13 | user.name = name; 14 | user.createTime = new Date(); 15 | 16 | return user; 17 | } 18 | 19 | public String getId() { 20 | return id; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public Date getCreateTime() { 28 | return createTime; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/service/LikeService.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.service; 2 | 3 | import com.vincent.demo.log.QueryHistoryService; 4 | import com.vincent.demo.model.LikePO; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.cache.annotation.CacheEvict; 9 | import org.springframework.cache.annotation.Cacheable; 10 | import org.springframework.cache.annotation.Caching; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.ArrayList; 14 | import java.util.HashSet; 15 | import java.util.List; 16 | import java.util.Set; 17 | 18 | @Service 19 | public class LikeService { 20 | private static final Logger logger = LoggerFactory.getLogger(LikeService.class); 21 | 22 | private final Set likeDB = new HashSet<>(); 23 | 24 | @Autowired 25 | private UserService userService; 26 | 27 | @Autowired 28 | private QueryHistoryService historyService; 29 | 30 | @Caching( 31 | evict = { 32 | @CacheEvict(cacheNames = "likeUserNames", key = "#postId"), 33 | @CacheEvict(cacheNames = "likeCount", key = "#p1") 34 | } 35 | ) 36 | public void createLike(String userId, String postId) { 37 | var like = LikePO.of(userId, postId); 38 | likeDB.add(like); 39 | } 40 | 41 | @Cacheable(cacheNames = "likeCount", key = "#postId") 42 | public long getLikeCount(String postId) { 43 | logNotReadFromCache("likeCount", postId); 44 | return likeDB.stream() 45 | .filter(like -> like.getPostId().equals(postId)) 46 | .count(); 47 | } 48 | 49 | @Cacheable(cacheNames = "likeUserNames", key = "#postId") 50 | public List getLikeUserNames(String postId) { 51 | logNotReadFromCache("likeUserNames", postId); 52 | 53 | var userIds = likeDB.stream() 54 | .filter(like -> like.getPostId().equals(postId)) 55 | .map(LikePO::getUserId) 56 | .toList(); 57 | var userIdToNameMap = userService.getUserIdToNameMap(userIds); 58 | var names = userIds.stream() 59 | .map(userIdToNameMap::get) 60 | .toList(); 61 | return new ArrayList<>(names); 62 | } 63 | 64 | public void deleteAll() { 65 | likeDB.clear(); 66 | } 67 | 68 | private void logNotReadFromCache(String type, String identifier) { 69 | logger.info("Not read data from cache: {}-{}", type, identifier); 70 | historyService.add(type, identifier); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/service/PostService.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.service; 2 | 3 | import com.vincent.demo.log.QueryHistoryService; 4 | import com.vincent.demo.model.PostPO; 5 | import com.vincent.demo.model.PostVO; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.cache.annotation.Cacheable; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.*; 13 | 14 | @Service 15 | public class PostService { 16 | private static final Logger logger = LoggerFactory.getLogger(PostService.class); 17 | 18 | private final Map postDB = new HashMap<>(); 19 | 20 | @Autowired 21 | private UserService userService; 22 | 23 | @Autowired 24 | private LikeService likeService; 25 | 26 | @Autowired 27 | private QueryHistoryService historyService; 28 | 29 | public PostPO createPost(String id, String userId, String title) { 30 | var post = PostPO.of(id, userId, title); 31 | postDB.put(post.getId(), post); 32 | 33 | return post; 34 | } 35 | 36 | public PostVO getPost(String id) { 37 | var postPO = postDB.get(id); 38 | var creatorName = userService.getUser(postPO.getCreatorId()).getName(); 39 | var likeUserNames = likeService.getLikeUserNames(id); 40 | 41 | return PostVO.of(postPO, creatorName, likeUserNames); 42 | } 43 | 44 | @Cacheable(cacheNames = "post", key = "'mostLikedPosts'") 45 | public List getMostLikedPosts() { 46 | logNotReadFromCache("post", "mostLikedPosts"); 47 | 48 | var postToLikeCountMap = new HashMap(); 49 | postDB.values() 50 | .forEach(post -> { 51 | var likeCount = likeService.getLikeCount(post.getId()); 52 | postToLikeCountMap.put(post.getId(), likeCount); 53 | }); 54 | 55 | var posts = postToLikeCountMap.entrySet() 56 | .stream() 57 | .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) 58 | .limit(3) 59 | .map(x -> getPost(x.getKey())) 60 | .toList(); 61 | return new ArrayList<>(posts); 62 | } 63 | 64 | public void deleteAll() { 65 | postDB.clear(); 66 | } 67 | 68 | private void logNotReadFromCache(String type, String identifier) { 69 | logger.info("Not read data from cache: {}-{}", type, identifier); 70 | historyService.add(type, identifier); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/vincent/demo/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo.service; 2 | 3 | import com.vincent.demo.log.QueryHistoryService; 4 | import com.vincent.demo.model.UserPO; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.cache.annotation.CachePut; 9 | import org.springframework.cache.annotation.Cacheable; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.*; 13 | import java.util.stream.Collectors; 14 | 15 | @Service 16 | public class UserService { 17 | private static final Logger logger = LoggerFactory.getLogger(UserService.class); 18 | 19 | private final Map userDB = new HashMap<>(); 20 | 21 | @Autowired 22 | private QueryHistoryService historyService; 23 | 24 | @CachePut(cacheNames = "user", key = "#id", condition = "#saveCache") 25 | public UserPO createUser(String id, String name, boolean saveCache) { 26 | var user = UserPO.of(id, name); 27 | userDB.put(user.getId(), user); 28 | return user; 29 | } 30 | 31 | @CachePut(cacheNames = "user", key = "#user.id") 32 | public UserPO updateUser(UserPO user) { 33 | userDB.put(user.getId(), user); 34 | return user; 35 | } 36 | 37 | @Cacheable(cacheNames = "user", key = "#p0", unless = "#result.id.startsWith('test-')") 38 | public UserPO getUser(String id) { 39 | logNotReadFromCache("user", id); 40 | return userDB.get(id); 41 | } 42 | 43 | public Map getUserIdToNameMap(Collection ids) { 44 | // In real project, you may have something like "UserRepository.findByIdIn(ids)". It just needs 1 DB operation. 45 | return ids.stream() 46 | .map(userDB::get) 47 | .filter(Objects::nonNull) 48 | .collect(Collectors.toMap(UserPO::getId, UserPO::getName)); 49 | } 50 | 51 | public void deleteAll() { 52 | userDB.clear(); 53 | } 54 | 55 | private void logNotReadFromCache(String type, String identifier) { 56 | logger.info("Not read data from cache: {}-{}", type, identifier); 57 | historyService.add(type, identifier); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.redis.host=localhost 2 | spring.redis.port=6379 3 | spring.redis.password= 4 | spring.redis.database=0 -------------------------------------------------------------------------------- /src/test/java/com/vincent/demo/CacheTests.java: -------------------------------------------------------------------------------- 1 | package com.vincent.demo; 2 | 3 | import com.vincent.demo.log.QueryHistoryService; 4 | import com.vincent.demo.model.UserPO; 5 | import com.vincent.demo.service.LikeService; 6 | import com.vincent.demo.service.PostService; 7 | import com.vincent.demo.service.UserService; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | import org.springframework.cache.Cache; 14 | import org.springframework.cache.CacheManager; 15 | import org.springframework.test.context.junit4.SpringRunner; 16 | 17 | import java.util.List; 18 | import java.util.Optional; 19 | import java.util.stream.Stream; 20 | 21 | import static org.junit.Assert.*; 22 | 23 | @RunWith(SpringRunner.class) 24 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 25 | public class CacheTests { 26 | @Autowired 27 | private UserService userService; 28 | 29 | @Autowired 30 | private LikeService likeService; 31 | 32 | @Autowired 33 | private PostService postService; 34 | 35 | @Autowired 36 | private QueryHistoryService historyService; 37 | 38 | @Autowired 39 | private CacheManager cacheManager; 40 | 41 | @Before 42 | public void clearData() { 43 | userService.deleteAll(); 44 | likeService.deleteAll(); 45 | postService.deleteAll(); 46 | historyService.deleteAll(); 47 | Stream.of("user", "likeUserNames", "likeCount", "post").forEach(cacheName -> 48 | Optional.ofNullable(cacheManager.getCache(cacheName)).ifPresent(Cache::clear)); 49 | } 50 | 51 | @Test 52 | public void testCreateUserThenCache() { 53 | var createdUser = userService.createUser("U1", "Vincent", true); 54 | var resultUser = userService.getUser(createdUser.getId()); 55 | 56 | assertEquals(createdUser.getId(), resultUser.getId()); 57 | assertEquals(createdUser.getName(), resultUser.getName()); 58 | assertEquals(createdUser.getCreateTime(), resultUser.getCreateTime()); 59 | assertFalse(historyService.contains("user", createdUser.getId())); 60 | } 61 | 62 | @Test 63 | public void testCreateUserWithoutCache() { 64 | var createdUser = userService.createUser("U1", "Vincent", false); 65 | 66 | var resultUser = userService.getUser(createdUser.getId()); 67 | assertTrue(historyService.contains("user", createdUser.getId())); 68 | historyService.deleteAll(); 69 | 70 | resultUser = userService.getUser(createdUser.getId()); 71 | assertEquals(createdUser.getId(), resultUser.getId()); 72 | assertEquals(createdUser.getName(), resultUser.getName()); 73 | assertFalse(historyService.contains("user", createdUser.getId())); 74 | } 75 | 76 | @Test 77 | public void testConditionalCacheable() { 78 | var user = userService.createUser("test-U1", "Andy", false); 79 | 80 | // the prefix "test-" of id make this data always non cacheable 81 | for (var i = 0; i < 2; i++) { 82 | userService.getUser(user.getId()); 83 | assertTrue(historyService.contains("user", user.getId())); 84 | historyService.deleteAll(); 85 | } 86 | } 87 | 88 | @Test 89 | public void testUpdateUser() { 90 | var createdUser = userService.createUser("U1", "Vincent", true); 91 | var updatedUser = UserPO.of(createdUser.getId(), "Vincent Zheng"); 92 | userService.updateUser(updatedUser); 93 | 94 | var resultUser = userService.getUser(createdUser.getId()); 95 | assertEquals(updatedUser.getId(), resultUser.getId()); 96 | assertEquals(updatedUser.getName(), resultUser.getName()); 97 | assertFalse(historyService.contains("user", createdUser.getId())); 98 | } 99 | 100 | @Test 101 | public void testGetPostCreatorName() { 102 | var creator = userService.createUser("U1", "Vincent", false); 103 | var postPO = postService.createPost("P1", creator.getId(), "Cache Tutorial"); 104 | 105 | var postVO = postService.getPost(postPO.getId()); 106 | assertEquals(creator.getName(), postVO.getCreatorName()); 107 | assertTrue(historyService.contains("user", creator.getId())); 108 | historyService.deleteAll(); 109 | 110 | postVO = postService.getPost(postPO.getId()); 111 | assertEquals(creator.getName(), postVO.getCreatorName()); 112 | assertFalse(historyService.contains("user", creator.getId())); 113 | } 114 | 115 | @Test 116 | public void testGetPostLikeUserNames() { 117 | var creatorUser = userService.createUser("U1", "Vincent", false); 118 | var postPO = postService.createPost("P1", creatorUser.getId(), "Post_1"); 119 | 120 | // create first like 121 | var likeUser1 = userService.createUser("U2", "Ivy", false); 122 | likeService.createLike(likeUser1.getId(), postPO.getId()); 123 | 124 | var postVO = postService.getPost(postPO.getId()); 125 | assertEquals(1, postVO.getLikerNames().size()); 126 | assertTrue(postVO.getLikerNames().contains(likeUser1.getName())); 127 | assertTrue(historyService.contains("likeUserNames", postPO.getId())); 128 | historyService.deleteAll(); 129 | 130 | postService.getPost(postPO.getId()); 131 | assertFalse(historyService.contains("likeUserNames", postPO.getId())); 132 | assertFalse(historyService.contains("user", likeUser1.getId())); 133 | 134 | // create second like 135 | var likeUser2 = userService.createUser("U3", "Dora", false); 136 | likeService.createLike(likeUser2.getId(), postPO.getId()); 137 | 138 | postVO = postService.getPost(postPO.getId()); 139 | assertEquals(2, postVO.getLikerNames().size()); 140 | assertTrue(postVO.getLikerNames().containsAll( 141 | List.of(likeUser1.getName(), likeUser2.getName()))); 142 | assertTrue(historyService.contains("likeUserNames", postPO.getId())); 143 | } 144 | 145 | @Test 146 | public void testGetMostLikedPosts() { 147 | var creatorUser1 = userService.createUser("U1", "Vincent", true); 148 | var creatorUser2 = userService.createUser("U2", "Ivy", true); 149 | var creatorUser3 = userService.createUser("U3", "Dora", true); 150 | 151 | var postPO1 = postService.createPost("P1", creatorUser1.getId(), "Title_1"); 152 | var postPO2 = postService.createPost("P2", creatorUser2.getId(), "Title_2"); 153 | var postPO3 = postService.createPost("P3", creatorUser3.getId(), "Title_3"); 154 | 155 | likeService.createLike(creatorUser1.getId(), postPO1.getId()); 156 | likeService.createLike(creatorUser2.getId(), postPO1.getId()); 157 | likeService.createLike(creatorUser3.getId(), postPO1.getId()); 158 | likeService.createLike(creatorUser2.getId(), postPO2.getId()); 159 | likeService.createLike(creatorUser3.getId(), postPO2.getId()); 160 | likeService.createLike(creatorUser3.getId(), postPO3.getId()); 161 | 162 | var postVOs = postService.getMostLikedPosts(); 163 | assertEquals(3, postVOs.size()); 164 | assertEquals(postPO1.getId(), postVOs.get(0).getId()); 165 | assertEquals(postPO2.getId(), postVOs.get(1).getId()); 166 | assertEquals(postPO3.getId(), postVOs.get(2).getId()); 167 | assertTrue(historyService.contains("post", "mostLikedPosts")); 168 | historyService.deleteAll(); 169 | 170 | postVOs = postService.getMostLikedPosts(); 171 | assertEquals(3, postVOs.size()); 172 | assertEquals(postPO1.getId(), postVOs.get(0).getId()); 173 | assertEquals(postPO2.getId(), postVOs.get(1).getId()); 174 | assertEquals(postPO3.getId(), postVOs.get(2).getId()); 175 | assertFalse(historyService.contains("post", "mostLikedPosts")); 176 | } 177 | } -------------------------------------------------------------------------------- /src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.redis.host=localhost 2 | spring.redis.port=6379 3 | spring.redis.password= 4 | spring.redis.database=0 --------------------------------------------------------------------------------