我正在尝试编写一个动态运行外部类'测试的方法。我能够运行仅使用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似乎只加载正在测试的类而不加载外部项目类路径中定义的依赖项(如jar)。我不知道如何动态地将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"));
提前致谢,
Mark Cachia
答案 0 :(得分:0)
我不确定你的意思:
我认为这个问题与类路径有关,就像ClassLoader一样 看似只加载正在测试的类而且没有加载 在外部项目的类路径中定义的依赖项(如jar)。
如果要访问java中的类,则必须将其放在类路径上,或者自己查找并加载它。看起来您正在使用自己的类加载器将Eclipse项目bin路径添加到类路径中,但是Mockery没有添加到类路径中。 Eclipse bin路径仅包含已编译的类。您需要专门加载Mockery jar,或者更好,只需使用java -cp
将所有内容放入jvm的类路径中。
好的,我开始明白这个问题了。您正尝试在某个elses项目中运行一组测试,但如果测试引用其他依赖项,则它不起作用。简短的回答是:这很难。您正在尝试根据外部项目的引用类/ 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
还有额外的奖励,如果你跑步&amp;在jenkins下构建项目你也可以得到很好的报告。
答案 1 :(得分:0)
如果要加载正在运行测试的应用程序中使用的库,您需要设置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
}