2

我正在尝试编写一个动态运行外部类测试的方法。我能够运行仅使用 JDK 库的测试,但是当我运行使用另一个库(例如 org.jmock.Mockery)的测试时,JUnitCore.run(args) 返回的 Result 对象有以下错误:

[initializationError(package.TestClass): org/jmock/Mockery]
java.lang.NoClassDefFoundError: org/jmock/Mockery

com.sun.jdi.ClassNotLoadedException: Type has not been loaded occurred while retrieving component type of array.

不用说,如果我从 Eclipse 中的原始项目运行它们,测试就会运行并通过。

我相信这个问题与类路径有关,因为 ClassLoader 似乎只加载正在测试的类,而不加载外部项目的类路径中定义的依赖项(如 jars)。我不知道如何将 jar 动态加载到正在执行的应用程序中。

下面是加载类和运行测试的代码。

URL url = new File("E:\eclipseProjectName\bin\").toURL();
final URL[] urls = new URL[] { url };
final ClassLoader cl = new URLClassLoader(urls);
@SuppressWarnings("rawtypes")
final Class cls = cl.loadClass("package.ClassName");
final JUnitCore core = new JUnitCore();
final Result result = new JUnitCore().run(Request.method(cls, "methodName"));

提前致谢,

马克卡奇亚

4

2 回答 2

1

如果您想加载您在运行测试的应用程序中使用的库,您将需要设置您URLClassLoader以加载当前的类加载器,然后引用您尝试测试的类

 URLClassLoader cl = new URLClassLoader(classLoaderUrls, getClass().getClassLoader());

这是一个从 jar 动态加载类的示例。如果您只想按其名称加载一个类,您可以像上面那样。

    File pathToJar = new File(jarPath);

    JarFile jarFile;
    jarFile = new JarFile(pathToJar);
    Enumeration<JarEntry> e = jarFile.entries();

    URL[] classLoaderUrls = new URL[]{pathToJar.toURI().toURL()};

    URLClassLoader cl = new URLClassLoader(classLoaderUrls, getClass().getClassLoader());
    while (e.hasMoreElements()) {

        // load all the classes in the jar (or you can set it up to use the exact class/method name as you did above
        JarEntry je = e.nextElement();
        if(je.isDirectory() || !je.getName().endsWith(".class")){
            continue;
        }
        // -6 because of .class
        String className = je.getName().substring(0,je.getName().length()-6);
        className = className.replace('/', '.');
        Class c = cl.loadClass(className);


        JUnitCore junit = new JUnitCore();
        Result result = junit.runClasses(c);
        // check for failed/ passed tests here

     }
于 2016-07-15T16:54:16.993 回答
0

我不确定你的意思是:

我相信这个问题与类路径有关,因为 ClassLoader 似乎只加载正在测试的类,而不是加载在外部项目的 classpath 中定义的依赖项(如 jars)

如果你想访问 java 中的一个类,你必须要么把它放在类路径中,要么自己找到并加载它。似乎您正在使用自己的类加载器将 Eclipse 项目 bin 路径添加到类路径中,但 Mockery 并未添加到类路径中。Eclipse bin 路径仅包含您已编译的类。您需要专门加载 Mockery jar,或者更好的是,只需使用java -cp.

好的,我开始明白这个问题了。您正在尝试在其他人的项目中运行一组测试,但如果测试引用其他依赖项,它就不起作用。简短的回答是:这很难。您正在尝试根据外部项目的引用类/jar 确定需要将哪些类添加到 classLoader。

有几种方法可以做到这一点。如果您确定外部项目是使用 Eclipse 构建的,那么您可以查看.project.classpath找到外部项目的依赖项。这并不简单,因为这些可以包含对其他容器的引用。这是我的一个项目中的 .classpath:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
  <classpathentry kind="src" output="target/classes" path="src/main/java"/>
  <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
  <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
  <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
  <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
  <classpathentry kind="output" path="target/classes"/>
</classpath>

这包含对容器的引用,例如 Maven 容器。如果您认为这对您的项目来说是可以实现的,那么这可能是实现这一目标的一种方法。一个更好的方法是强制使用 maven 或类似的,然后你可以运行测试只是

$ mvn test

额外的好处是,如果你在 jenkins 下运行和构建项目,你也会得到很好的报告。

于 2012-03-09T12:54:26.893 回答