Unit test using the Reflections google library fails only when executed by Maven

前端 未结 5 1198
有刺的猬
有刺的猬 2020-12-18 00:00

I am using the Google Reflections library for querying certain resources in the classpath. Those resources are located in the same location than the classes in my project.

相关标签:
5条回答
  • 2020-12-18 00:10

    I just encountered the same problem with Reflections library (version 0.9.11), only when executing unit tests from Maven builds. The link provided in the accepted answer pointed me in the right direction.

    A simple POM file change to my Surefire plugin fixed this:

                <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.21.0</version>
                <configuration>
                    <useSystemClassLoader>false</useSystemClassLoader>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.21.0</version>
                <configuration>
                    <useSystemClassLoader>false</useSystemClassLoader>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
    

    The <useSystemClassLoader> config parameter defaults to 'true'. Forcing it to 'false' seems to resolve the classloader problem in my unit tests.

    0 讨论(0)
  • 2020-12-18 00:19

    You're probably using M2Eclipse, which adds stuff to the classpath on its own. Command-line Maven works differently. You might find some options that will help.

    0 讨论(0)
  • 2020-12-18 00:19

    Solved it. Posting the solution in case someone find the same problem in the future.

    When executing the unit tests of a project, Maven does not (explicitly) include in the classpath all its dependencies. Instead, it declares a dependency on a tmp jar located in "target/surefire/surefirebooter_NUMBER_THAT_LOOKS_LIKE_TIME_STAMP.jar". This jar only contains a manifest file that declares a classpath for the project.

    The method forClassLoader in the Reflections library does not return a set of urls with the effective classpath (i.e., classpath entries in manifest files are ignored). To overcome this, I just implemented this simple method:

    public static Set<URL> effectiveClassPathUrls(ClassLoader... classLoaders) {
        return ClasspathHelper.forManifest(ClasspathHelper.forClassLoader(classLoaders));
    }
    

    The method forManifest (also part of the Reflections library) adds to the set of classpath urls sent as parameter, the missing classpath entries declared in manifest files of any jar files contained in the set. In this way the method returns a set of URLs with the effective classpath of the project.

    0 讨论(0)
  • 2020-12-18 00:28

    I had the exact same problem. Adding following URL did the trick for me.

    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.setUrls(...);
    cb.addUrls(YourClassName.class.getProtectionDomain().getCodeSource().getLocation());
    
    0 讨论(0)
  • 2020-12-18 00:31

    There are a few issues you can create that makes surefire fail.

    1. there is a naming convention; test suites should be called 'TestBlaBla' or 'BlaBlaTest'; beginning or ending with the word 'Test'.

    2. as mentioned earlier, the classpath in Maven is more restricted than it is in Eclipse as Eclipse (stupidly) does not separate the compile classpath from the test classpath.

    3. Surefire is free to run test cases from different test suites in any order. When running multiple test suites that initialize some common base (such as an in-memory database or a JNDI context) that can create conflicts where test suites start to influence each other. You need to take care to properly isolate test suites. Tricks I use are to use separate in-memory databases for suites, and I initialize shared things per unit test in stead of per test suite.

    3 is the hardest to debug I can tell you; whenever something works in Eclipse and not in Maven I naturally assume I'm doing something wrong in isolating the test suite.

    0 讨论(0)
提交回复
热议问题