我对如何组织和测试如下代码有一个概念上的疑问,其中对辅助方法的调用是该类的所有公共方法的第一条指令。我的想法是使代码清洁和可测试。
代码是一个尝试通过类“缓存”来说明这一点的示例。如果设置了此类,则该类具有可选前缀,将应用于缓存中的所有键。
import java.util.HashMap;
public class Cache {
private HashMap<String, Integer> inMemoryCache;
private String prefix;
public Cache() {
this.inMemoryCache = new HashMap<String, Integer>();
prefix = null;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public int getValue(String key) throws NullPointerException {
String prefixedKey = applyPrefixOrDefault(key);
return inMemoryCache.get(prefixedKey);
}
public void setValue(String key, int value) {
String prefixedKey = applyPrefixOrDefault(key);
inMemoryCache.put(prefixedKey, value);
}
public boolean isCached(String key) {
String prefixedKey = applyPrefixOrDefault(key);
return inMemoryCache.containsKey(prefixedKey);
}
private String applyPrefixOrDefault(String key) {
if (prefix == null) {
return key;
} else {
return prefix + key;
}
}
public static void main (String[] arg) {
Cache cache = new Cache();
cache.setPrefix("global:");
cache.setValue("id", 4);
int value = cache.getValue("id");
System.out.println(value);
}
}
此代码向我提出了两个问题:
如果我有很多方法访问内部哈希表,那么将一个类中的缓存行为与其他类中的前缀行为分开是正确的吗?
测试这个最干净的方法是什么?如果我们不考虑前缀,测试getValue,setValue和isCached很简单。使用前缀我们需要测试两件事,缓存的正确内部行为,我们还需要测试所有方法在访问数据之前调用applyPrefixOrDefault。
这是一个常见的用例,我确信必须有一些设计模式来组织它。有什么想法吗?
答案 0 :(得分:1)
在我看来,我们在这里想念的是一个构造函数,让我们设置缓存的状态。所以我会按如下方式添加一个:
public Cache() {
this(null, new HashMap<String, Integer>());
}
public Cache(String prefix, Map<String, Integer> cache) {
this.prefix = prefix;
this.inMemoryCache = cache;
}
使用这个新构造函数,您应该能够为每个可能的缓存状态编写测试用例。我还会将applyPrefixOrDefault
方法的可见性更改为protected或package,以便测试代码可以访问它。例如,要测试GetValue方法,我会写:
public class EmptyCacheTests {
private final Map<String, Integer> memory;
private final String prefix;
private final Cache cache;
public EmptyCacheTests() {
this.memory = new HasMap<String, Integer>();
this.prefix = "foo";
this.cache = new Cache(prefix, memory);
}
public void testGetValue() {
String key = this.cache.applyPrefixOrDefault("bar")
this.memory.put(key, 50);
result = this.cache.getValue("bar");
assertEquals(50, result, "The value retrieved is wrong!");
}
}
这一点,它允许测试设置缓存的内部状态,以便我们可以测试许多不同的。