简体   繁体   English

如何运行带有阴影依赖项的单元测试?

[英]How to run unit tests with shaded dependencies?

I am running into test failures with a maven project that I do not understand. 我正在使用一个我不了解的Maven项目遇到测试失败。

The maven project is set up as a multi-module project, and it shaded one of its dependencies (Google Guava, because Spark itself has a conflicting dependency for Google Guava). Maven项目被设置为一个多模块项目,并且它遮蔽了其依赖项之一(Google Guava,因为Spark本身对Google Guava的依赖项存在冲突)。

Below is a simplified version of the parent pom: 以下是父pom的简化版本:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    ... other stuff...

    <modules>
        <module>module A</module>
        <module>module B</module>
        <module>module C</module>
        ...
    </modules>

    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.0-jre</version>
        </dependency>
        ...other dependencies

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.3</version>
                <executions>
                    <execution>
                        <id>relocateGuava</id>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <relocations>
                                <relocation>
                                    <pattern>com.google</pattern>
                                    <shadedPattern>shaded.com.google</shadedPattern>
                                </relocation>
                            </relocations>
                        </configuration>
                    </execution>
                    <execution>
                        <id>buildUberJar</id>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>reference.conf</resource>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
        </plugins>
    </build>
</project>

The failure includes this: 失败包括:

Caused by: java.lang.ClassNotFoundException: shaded.com.google.common.collect.Multimap
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 22 more

and the offending line is a simple import statement in module A: import com.google.common.collect.ListMultimap; 令人讨厌的行是模块A中的简单导入语句: import com.google.common.collect.ListMultimap; .

The dependency structure is like this: - module B is the one whose tests are failing - module B names module A as a dependency - module A includes that import statement 依赖关系结构如下:-模块B是测试失败的模块-模块B将模块A命名为依赖关系-模块A包含该import语句

Here is a simplified version of module B's pom: 这是模块B的pom的简化版本:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <dependencies>
        <dependency>
            module A
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.7</version>
                <executions>
                    <execution>
                        <id>default-deploy</id>
                        <phase>none</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

I think what might be happening is that module B's tests are run before its dependencies are shaded. 认为可能正在发生的事情是在对模块B的依赖项进行着色之前运行模块B的测试。 So basically, the module B code that's being tested doesn't include the shaded dependencies in the classpath. 因此,基本上,正在测试的模块B代码在类路径中不包括阴影依赖项。 However, B depends on A, and A's code has been rewritten to point at the shaded dependencies rather than the original dependencies. 但是,B依赖于A,并且A的代码被重写以指向阴影的依赖关系,而不是原始的依赖关系。 So when B includes A's code, it's including the code that is pointing at the shaded dependencies, and those shaded dependencies are not available to B. 因此,当B包含A的代码时,它包含的代码指向阴影依赖项,而这些阴影依赖项对B不可用。

Questions: - Is that is what is happening? 问题:-这是怎么回事吗? - How can I fix it? -我该如何解决?

(If you can't tell, I'm very inexperienced with both Java and Maven) (如果您不知道,我对Java和Maven都缺乏经验)

EDIT: Will also add that mvn package succeeds -- only mvn test fails. 编辑:还将添加mvn package成功-仅mvn test失败。

I think you may got wrong verion of google-guava, there are three ways you can try: 我认为您可能对谷歌番石榴的版本有误,可以尝试以下三种方法:

  1. Delete your local directory of google-guave which is keeping in your local maven repository and reimport the whole depedencies of your project, i used to use this way to resolve my problem years ago. 删除保存在本地Maven存储库中的google-guave本地目录,然后重新导入项目的整个依赖关系,几年前我曾使用这种方式来解决问题。

  2. Execute maven install for module A, so you can find the module A in your local maven repository, if maven install get error for module A, it must something wrong in module A, so we can exclude module B's problem. 对模块A执行maven安装,因此您可以在本地maven存储库中找到模块A,如果maven install在模块A上出错,那么它在模块A中一定有问题,因此我们可以排除模块B的问题。

  3. Explicitly define google-guava dependency in Module B, so when you run test case, maven will get google-guava dependency from module B, project's dependency of google-guava will be covered. 在模块B中明确定义google-guava依赖关系,因此在运行测试用例时,maven将从模块B中获取google-guava依赖关系,将涵盖项目对google-guava的依赖关系。

if three way above not work well for your probelm, i hope you can execute mvn dependency:list and which dependencies you actual get, when you run test case, especially attention on google-guava's verion, check its version is just right define in project's pom.xml 如果以上三种方法都不适合您的探针,我希望您可以执行mvndependency mvn dependency:list以及您实际获得的依赖,在运行测试用例时,尤其要注意google-guava的版本,请检查其版本是否正确在项目的pom.xml

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

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