对不同的JUnit测试使用不同的类加载器?

时间:2020-03-05 18:47:08  来源:igfitidea点击:

我有一个Singleton / Factory对象,我想为其编写JUnit测试。 Factory方法根据类路径上属性文件中的类名称决定实例化哪个实现类。如果找不到属性文件,或者属性文件不包含类名键,则该类将实例化默认实现类。

由于工厂一旦实例化就保留了Singleton的静态实例以供使用,为了能够在Factory方法中测试"故障转移"逻辑,我需要在不同的类加载器中运行每个测试方法。

JUnit(或者另一个单元测试包)有什么办法做到这一点?

编辑:这是一些正在使用的工厂代码:

private static MyClass myClassImpl = instantiateMyClass();

private static MyClass instantiateMyClass() {
    MyClass newMyClass = null;
    String className = null;

    try {
        Properties props = getProperties();
        className = props.getProperty(PROPERTY_CLASSNAME_KEY);

        if (className == null) {
            log.warn("instantiateMyClass: Property [" + PROPERTY_CLASSNAME_KEY
                    + "] not found in properties, using default MyClass class [" + DEFAULT_CLASSNAME + "]");
            className = DEFAULT_CLASSNAME;
        }

        Class MyClassClass = Class.forName(className);
        Object MyClassObj = MyClassClass.newInstance();
        if (MyClassObj instanceof MyClass) {
            newMyClass = (MyClass) MyClassObj;
        }
    }
    catch (...) {
        ...
    }

    return newMyClass;
}

private static Properties getProperties() throws IOException {

    Properties props = new Properties();

    InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(PROPERTIES_FILENAME);

    if (stream != null) {
        props.load(stream);
    }
    else {
        log.error("getProperties: could not load properties file [" + PROPERTIES_FILENAME + "] from classpath, file not found");
    }

    return props;
}

解决方案

回答

当我遇到这种情况时,我更喜欢使用一些技巧。我可能改为公开一个受保护的方法,例如reinitialize(),然后从测试中调用此方法,以有效地将工厂设置回其初始状态。这种方法仅适用于测试用例,因此我将其记录下来。

这有点hack,但是它比其他选项容易得多,并且我们不需要第三方库(尽管如果我们更喜欢一个更清洁的解决方案,则可能有一些第三方工具可供我们使用)可以用)。

回答

我们可以通过再次调用instantiateMyClass()来使用Reflection设置myClassImpl。看一下这个答案,以查看用于私有方法和变量的示例模式。