2017-02-20 22 views
0

У меня есть концептуальное сомнение в том, как организовать и протестировать код, как показано ниже, где вызов вспомогательного метода является первой инструкцией всех общедоступных методов класса. Моя идея делает код чистым и проверяемым.Как организовать и проверить этот код?

Код является примером, чтобы попытаться проиллюстрировать это классом «cache». Этот класс имеет необязательный префикс, который будет применяться ко всем ключам в кеше, если он установлен.

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 перед доступом к данным.

Это обычный случай использования, и я уверен, что для его организации должен быть какой-то шаблон дизайна. Есть идеи?

ответ

1

На мой взгляд, мы пропустим здесь конструктор, который позволяет установить состояние кэша. Поэтому я хотел бы добавить один следующим образом:

public Cache() { 
    this(null, new HashMap<String, Integer>()); 
} 

public Cache(String prefix, Map<String, Integer> cache) { 
    this.prefix = prefix; 
    this.inMemoryCache = cache; 
} 

С помощью этого нового конструктора, вы должны быть в состоянии написать тест-кейсы для каждого возможного состояния кэша. Я также изменил бы видимость метода applyPrefixOrDefault для защиты или упаковки, чтобы тестовый код мог получить к нему доступ. Например, чтобы проверить метод 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!"); 
    } 
} 

Дело тут, чтобы тест, чтобы настроить внутреннее состояние кэша, так что мы можем тогда тест на многих разных.

+0

И если у меня было много методов (например, 10-20 методов), рассмотрите ли вы разделение поведения префикса в отдельном классе или дублируете ли вы все тестовые примеры (с префиксом и без префикса)? – Garet

+0

Да, если вы хотите протестировать префикс и без него, разделение вычисления префикса в отдельном классе может позволить вам построить тест по составу, а не перечислять все возможные тестовые примеры. – Franck

+0

Думая об этом, атрибут 'prefix' не связан с кешем, а вычисляется/преобразуется ключ. Таким образом, я создаю объект KeyBuilder, который будет инкапсулировать этот префикс и будет выставлять метод 'transformKey', похожий на' applyPrefixOrDefault'. Затем можно добавить объект KeyBuilder в конструктор кеша, чтобы тест мог его определить. – Franck