当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《使用不同的类加载器进行不同的JUnit测试?》经验,为你挑选了1个好方法。

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

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

有没有办法使用JUnit(或其他单元测试包)来做到这一点?

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

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

AutomatedMik.. 38

这个问题可能已经过时了,但因为这是我遇到这个问题时最接近的答案,但我会描述我的解决方案.

使用JUnit 4

拆分你的测试,以便每个类有一个测试方法(这个解决方案只更改类之间的类加载器,而不是方法之间,因为父类运行器每个类收集一次所有方法)

@RunWith(SeparateClassloaderTestRunner.class)注释添加到测试类中.

创建SeparateClassloaderTestRunner如下所示:

public class SeparateClassloaderTestRunner extends BlockJUnit4ClassRunner {

    public SeparateClassloaderTestRunner(Class clazz) throws InitializationError {
        super(getFromTestClassloader(clazz));
    }

    private static Class getFromTestClassloader(Class clazz) throws InitializationError {
        try {
            ClassLoader testClassLoader = new TestClassLoader();
            return Class.forName(clazz.getName(), true, testClassLoader);
        } catch (ClassNotFoundException e) {
            throw new InitializationError(e);
        }
    }

    public static class TestClassLoader extends URLClassLoader {
        public TestClassLoader() {
            super(((URLClassLoader)getSystemClassLoader()).getURLs());
        }

        @Override
        public Class loadClass(String name) throws ClassNotFoundException {
            if (name.startsWith("org.mypackages.")) {
                return super.findClass(name);
            }
            return super.loadClass(name);
        }
    }
}

注意我必须这样做来测试在遗留框架中运行的代码,我无法改变.鉴于选择,我会减少使用静态和/或放入测试挂钩以允许系统重置.它可能不是很漂亮,但它允许我测试很多代码,否则很难.

此解决方案还打破了依赖于类加载技巧的其他任何东西,例如Mockito.



1> AutomatedMik..:

这个问题可能已经过时了,但因为这是我遇到这个问题时最接近的答案,但我会描述我的解决方案.

使用JUnit 4

拆分你的测试,以便每个类有一个测试方法(这个解决方案只更改类之间的类加载器,而不是方法之间,因为父类运行器每个类收集一次所有方法)

@RunWith(SeparateClassloaderTestRunner.class)注释添加到测试类中.

创建SeparateClassloaderTestRunner如下所示:

public class SeparateClassloaderTestRunner extends BlockJUnit4ClassRunner {

    public SeparateClassloaderTestRunner(Class clazz) throws InitializationError {
        super(getFromTestClassloader(clazz));
    }

    private static Class getFromTestClassloader(Class clazz) throws InitializationError {
        try {
            ClassLoader testClassLoader = new TestClassLoader();
            return Class.forName(clazz.getName(), true, testClassLoader);
        } catch (ClassNotFoundException e) {
            throw new InitializationError(e);
        }
    }

    public static class TestClassLoader extends URLClassLoader {
        public TestClassLoader() {
            super(((URLClassLoader)getSystemClassLoader()).getURLs());
        }

        @Override
        public Class loadClass(String name) throws ClassNotFoundException {
            if (name.startsWith("org.mypackages.")) {
                return super.findClass(name);
            }
            return super.loadClass(name);
        }
    }
}

注意我必须这样做来测试在遗留框架中运行的代码,我无法改变.鉴于选择,我会减少使用静态和/或放入测试挂钩以允许系统重置.它可能不是很漂亮,但它允许我测试很多代码,否则很难.

此解决方案还打破了依赖于类加载技巧的其他任何东西,例如Mockito.

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有