简体   繁体   English

如何使用JUnit在Maven项目中通过自定义类加载器两次加载同一类

[英]How to load same class by custom classloader twice in Maven project with JUnit

I did stackoverflowing like a mad two hours but nothing helped so far. 我确实疯狂了两个小时,但还是没什么帮助。

I have very very basic Maven project where I have some Singleton class. 我有一个非常基础的Maven项目,其中有一些Singleton课程。 There is said that it is possible to load singleton twice with different classloaders so I wrote my own but the issue is that I am not able to load that class because I am getting ClassNotFoundException but I do not have a clue why. 据说可以用不同的类加载器加载单例两次,所以我写了自己的类,但问题是我无法加载该类,因为我收到ClassNotFoundException,但我不知道为什么。

@RunWith(JUnit4.class)
public class SingletonClassLoadedDifferentClassLoadersTestCase {

    static class SingletonClassLoader extends ClassLoader {

        @Override
        public Class<?> loadClass(String className)
          throws ClassNotFoundException {
            try {
                InputStream is =
                    // seems to be the central problem 
                    ClassLoader.getSystemResourceAsStream(className);
                if (is == null) {
                    throw new ClassNotFoundException();
                }

                ByteArrayOutputStream buffer = new ByteArrayOutputStream();

                int nRead;
                byte[] data = new byte[1024];

                while ((nRead = is.read(data, 0, data.length)) != -1) {
                    buffer.write(data, 0, nRead);
                }

                byte[] classBytes = buffer.toByteArray();

                return defineClass(className, classBytes, 0, classBytes.length);
            } catch (IOException ex) {
                throw new ClassNotFoundException();
            }
        }
    }

    @Test
    public void singletonTest() throws Exception {
        Class<?> singleton1 = new SingletonClassLoader()
            .loadClass("SingletonLazy");
        Class<?> singleton2 = new SingletonClassLoader()
            .loadClass("SingletonLazy");
    }
}

SingletonLazy is just a class in src/main/java (burried in some package directory). SingletonLazy只是src / main / java中的一个类(位于某些包目录中)。 It seems that ClassLoader is unable to find that class but why? 看来ClassLoader无法找到该类,但是为什么呢? I see that it is not in target/test-classes . 我看到它不在 target/test-classes How do I tell Maven to somehow put that class in src/main/java/some/package/SingletonLazy.java on classpath while I do tests? 我如何在测试时告诉Maven如何将该类放在classpath的src / main / java / some / package / SingletonLazy.java中? I am executing it from the command line like mvn clean test 我正在像mvn clean test这样从命令行执行它

Thank you for any hint! 谢谢您的提示!

Don't use SystemClassLoader. 不要使用SystemClassLoader。 Use the immediate classloader instead. 改用立即类加载器。 Change your code to, 将您的代码更改为

InputStream is = SingletonClassLoadedDifferentClassLoadersTestCase.class
      .getClassLoader()
      .getResourceAsStream(className);

I believe JUnit creates a separate classloader for each test. 我相信JUnit会为每个测试创建一个单独的类加载器。 I was under impression that JUnit is doing that to avoid the issues created by static state. 我印象深刻的是,JUnit这样做是为了避免由静态状态造成的问题。 I tried a few tests and I can see that it is not the case! 我尝试了几次测试,发现情况并非如此! Even if you have a class defined in src/test/java its static state is not erased, that is class is not reloaded per test. 即使您在src/test/java定义了一个类,其静态状态也不会被擦除,即该类不会在每次测试中重新加载。

Second thing I tried was to fork tests, but <forkMode>always</forkMode> which i believe highest level of forking works for only tests defined in two different test classes. 我尝试过的第二件事是派生测试,但是<forkMode>always</forkMode> ,我认为最高级别的派生仅适用于两个不同测试类中定义的测试。 If you have tests methods defined in the same class, all the test method runs will use the same JVM instance. 如果您在同一类中定义了测试方法,则所有运行的测试方法将使用相同的JVM实例。

Statics are inherently bad so I would recommend using an Inversion of Control (IOC) framework. 静电本质上是不好的,所以我建议使用控制反转(IOC)框架。 I have used Guice in past and its very lightweight and efficient. 我过去曾经使用过Guice,它非常轻巧高效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM