尝试使我的简单缓存通过所有单元测试,但在其中一个测试上仍然失败。

huangapple go评论187阅读模式
英文:

Trying to get my simple aged cache to pass all unit tests, keeps failing on one of them

问题

简单的年龄缓存:
我创建了一个简单的年龄缓存,并且已经使它通过了所有的单元测试,除了getExpired。我尝试在put之后和之前运行cleanExpiredRecords方法,但真的不知道该如何修复这个问题。任何建议将不胜感激。

  1. package io.collective;
  2. import java.time.Clock;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. public class SimpleAgedCache {
  6. private final Clock clock;
  7. private final Map<Object, CacheEntry> cacheMap;
  8. public SimpleAgedCache(Clock clock) {
  9. this.clock = clock;
  10. this.cacheMap = new HashMap<>();
  11. }
  12. public SimpleAgedCache() {
  13. this(Clock.system(Clock.systemDefaultZone().getZone()));
  14. }
  15. public void put(Object key, Object value, int retentionInMillis) {
  16. if (key != null && retentionInMillis > 0) {
  17. long expirationTime = clock.millis() + retentionInMillis;
  18. cacheMap.put(key, new CacheEntry(value, expirationTime));
  19. }
  20. }
  21. public boolean isEmpty() {
  22. return cacheMap.isEmpty();
  23. }
  24. public int size() {
  25. return cacheMap.size();
  26. }
  27. public Object get(Object key) {
  28. cleanExpiredRecords();
  29. CacheEntry entry = cacheMap.get(key);
  30. if (entry != null) {
  31. return entry.value;
  32. }
  33. return null;
  34. }
  35. private void cleanExpiredRecords() {
  36. long currentTime = clock.millis();
  37. cacheMap.entrySet().removeIf(entry -> entry.getValue().isExpired(currentTime));
  38. }
  39. private static class CacheEntry {
  40. Object value;
  41. long expirationTime;
  42. CacheEntry(Object value, long expirationTime) {
  43. this.value = value;
  44. this.expirationTime = expirationTime;
  45. }
  46. boolean isExpired(long currentTime) {
  47. return currentTime >= expirationTime;
  48. }
  49. boolean isNotExpired(long currentTime) {
  50. return !isExpired(currentTime);
  51. }
  52. }
  53. }

它一直失败的JUnit测试如下。我试图让我的代码通过单元测试。但是,它一直返回2,而期望的答案是1。
期望:1
实际:2

  1. @Test
  2. public void getExpired() {
  3. TestClock clock = new TestClock();
  4. SimpleAgedCache expired = new SimpleAgedCache(clock);
  5. expired.put("aKey", "aValue", 2000);
  6. expired.put("anotherKey", "anotherValue", 4000);
  7. clock.offset(Duration.ofMillis(3000));
  8. assertEquals(1, expired.size());
  9. assertEquals("anotherValue", expired.get("anotherKey"));
  10. }
英文:

Simple Aged Cache:
I have created a simple aged cache and I have got it to pass all unit tests except getExpired. I have tried running the cleanExpiredRecords method after the put, and before, really not sure how to fix this. Any suggestions would be appreciated.

  1. package io.collective;
  2. import java.time.Clock;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. public class SimpleAgedCache {
  6. private final Clock clock;
  7. private final Map&lt;Object, CacheEntry&gt; cacheMap;
  8. public SimpleAgedCache(Clock clock) {
  9. this.clock = clock;
  10. this.cacheMap = new HashMap&lt;&gt;();
  11. }
  12. public SimpleAgedCache() {
  13. this(Clock.system(Clock.systemDefaultZone().getZone()));
  14. }
  15. public void put(Object key, Object value, int retentionInMillis) {
  16. if (key != null &amp;&amp; retentionInMillis &gt; 0){
  17. long expirationTime = clock.millis() + retentionInMillis;
  18. cacheMap.put(key, new CacheEntry(value, expirationTime));
  19. }
  20. }
  21. public boolean isEmpty() {
  22. return cacheMap.isEmpty();
  23. }
  24. public int size() {
  25. return cacheMap.size();
  26. }
  27. public Object get(Object key) {
  28. cleanExpiredRecords();
  29. CacheEntry entry = cacheMap.get(key);
  30. if (entry != null){
  31. return entry.value;
  32. }
  33. return null;
  34. }
  35. private void cleanExpiredRecords(){
  36. long currentTime = clock.millis();
  37. cacheMap.entrySet().removeIf(entry -&gt; entry.getValue().isExpired(currentTime));
  38. }
  39. private static class CacheEntry{
  40. Object value;
  41. long expirationTime;
  42. CacheEntry(Object value, long expirationTime){
  43. this.value = value;
  44. this.expirationTime = expirationTime;
  45. }
  46. boolean isExpired(long currentTime){
  47. return currentTime &gt;= expirationTime;
  48. }
  49. boolean isNotExpired(long currentTime){
  50. return !isExpired(currentTime);
  51. }
  52. }
  53. }

The Junit test that it keeps failing is below. I am trying to get my code to pass the unit test. However, it keeps returning 2 when the expected answer is 1.
Expected :1
Actual :2

  1. @Test
  2. public void getExpired() {
  3. TestClock clock = new TestClock();
  4. SimpleAgedCache expired = new SimpleAgedCache(clock);
  5. expired.put(&quot;aKey&quot;, &quot;aValue&quot;, 2000);
  6. expired.put(&quot;anotherKey&quot;, &quot;anotherValue&quot;, 4000);
  7. clock.offset(Duration.ofMillis(3000));
  8. assertEquals(1, expired.size());
  9. assertEquals(&quot;anotherValue&quot;, expired.get(&quot;anotherKey&quot;));
  10. }

答案1

得分: 1

我不看到在两个 "puts" 和 "size-call" 之间会删除元素。

英文:

I don't see that elements will be removed between the two puts and the size-call.

答案2

得分: 1

你的清理方法在客户端调用get()时触发,但在调用size()时不会触发。换句话说,当你调用size()时,你的缓存实际上包含了两个键值对,并且仅在调用get()时才删除过期的记录。

这不应该失败:

  1. @Test
  2. public void getExpired() {
  3. TestClock clock = new TestClock();
  4. SimpleAgedCache expired = new SimpleAgedCache(clock);
  5. expired.put("aKey", "aValue", 2000);
  6. expired.put("anotherKey", "anotherValue", 4000);
  7. clock.offset(Duration.ofMillis(3000));
  8. assertEquals("anotherValue", expired.get("anotherKey"));
  9. assertEquals(1, expired.size());
  10. }
英文:

Your cleanup method is triggered when the client calls get(), but not when it calls size(). In other words, when you call size(), your cache actually holds two key -> value pairs, and the expired record is removed only when you call get().

This should not fail:

  1. @Test
  2. public void getExpired() {
  3. TestClock clock = new TestClock();
  4. SimpleAgedCache expired = new SimpleAgedCache(clock);
  5. expired.put(&quot;aKey&quot;, &quot;aValue&quot;, 2000);
  6. expired.put(&quot;anotherKey&quot;, &quot;anotherValue&quot;, 4000);
  7. clock.offset(Duration.ofMillis(3000));
  8. assertEquals(&quot;anotherValue&quot;, expired.get(&quot;anotherKey&quot;));
  9. assertEquals(1, expired.size());
  10. }

huangapple
  • 本文由 发表于 2023年8月11日 05:13:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76879334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定