如何组织和测试这段代码?

时间:2017-02-20 10:20:26

标签: testing design-patterns architecture software-design

我对如何组织和测试如下代码有一个概念上的疑问,其中对辅助方法的调用是该类的所有公共方法的第一条指令。我的想法是使代码清洁和可测试。

代码是一个尝试通过类“缓存”来说明这一点的示例。如果设置了此类,则该类具有可选前缀,将应用于缓存中的所有键。

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);
    }
}

此代码向我提出了两个问题:

  1. 如果我有很多方法访问内部哈希表,那么将一个类中的缓存行为与其他类中的前缀行为分开是正确的吗?

  2. 测试这个最干净的方法是什么?如果我们不考虑前缀,测试getValue,setValue和isCached很简单。使用前缀我们需要测试两件事,缓存的正确内部行为,我们还需要测试所有方法在访问数据之前调用applyPrefixOrDefault。

  3. 这是一个常见的用例,我确信必须有一些设计模式来组织它。有什么想法吗?

1 个答案:

答案 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!");
    }
}

这一点,它允许测试设置缓存的内部状态,以便我们可以测试许多不同的。