使用私有构造函数测试类

时间:2016-04-16 12:28:45

标签: java junit

我试图想出最好的方法来测试我当前正在使用的缓存类....我希望在测试中运行此类时替换下面的ClientFactory ....我想留下结构尽可能多的类,但因为它有一个私人构造函数我很难想到最好的测试方法..

public class MyCache {

private final long TIME_OUT

private static MyCache instance = null;

private final HashMap<String, MyObject> cache = new HashMap<String, MyObject>();

private MyCache() {
}

public static MyCache getInstance() {
    if (instance == null) {
        instance = new MyCache();
    }
    return instance;
}

public MyObject getDetails(String id) throws Exception {

    MyObject myObject = cache.get(id);
    if (myObject != null) {
        return myObject;
    } else {
        try {

            // want to be able to replace ClientFactory with test stub
            Client client = ClientFactory.createClient();
            myObject = client.getMyObject(id);

        } catch (NotFoundException nf) {
           .... log error
        } 

        return myObject;
    }
}

}

1 个答案:

答案 0 :(得分:1)

你可以做很多事情,但我认为从测试的角度看,Singleton-pattern不是一个好的选择。

  1. 如果您使用的是 Mockito ,则应将ClientFactory.createClient()调用解压缩到package-public(默认)函数中。 Mockito可以监视单身人士:spy(MyCache.class),你可以改变提取函数的行为。所以你替换了ClientFactory

  2. 您可以使用package-public构造函数替换private构造函数,还需要提取第一个解决方案中提到的函数。完成这些更改后,您可以在测试类中扩展MyCache(不使用 Mockito )。

  3. 您可以将MyCache的功能提取到包公共类中,该类不是单例(但不能从外部调用)。您可以很好地测试它,MyCache将只是提取类的单独包装。

  4. 我认为反射是反模式的,但我知道默认访问修饰符(空字符串)也有点难看。

    关于你的单身人士模式的几句话。如果您只有一个线程,这可不错,但如果您处于多线程环境中,则需要以下代码:

    // you need volatile, because of JVM thread caching
    private static volatile MyCache instance;
    
    private MyCache() {}
    
    public static MyCache getInstance() {
        if (instance == null) {
            synchronize(MyCache.class) {
                // yes, you need double check, because of threads
                if (instance == null) {
                    instance = new MyCache();
                }
            }
        }
        return instance;
    }