2

外部クラスのテストを動的に実行するメソッドを作成しようとしています。JDK ライブラリのみを使用するテストを実行できますが、org.jmock.Mockery などの別のライブラリを使用するテストを実行すると、JUnitCore.run(args) によって返される結果オブジェクトに次のエラーが発生します。

[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"));

前もって感謝します、

マーク・カチア

4

2 に答える 2

1

テストを実行しているアプリケーション内で使用しているライブラリをロードする場合はURLClassLoader、現在のクラスローダーをロードするようにセットアップしてから、テストしようとしているクラスへの参照をロードする必要があります。

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

jar からクラスを動的にロードする例を次に示します。1 つのクラスのみをその名前でロードしたい場合は、上記のようにできます。

    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 で定義された依存関係 (jar など) をロードしていないように見えるため、この問題はクラスパスに関連していると思います。

Java のクラスにアクセスしたい場合は、それをクラスパスに置くか、自分で見つけてロードする必要があります。独自のクラスローダーを使用して Eclipse プロジェクトの bin パスをクラスパスに追加しているようですが、Mockery はクラスパスに追加されていません。Eclipse の bin パスには、コンパイルしたクラスのみが含まれます。Mockery jar を明示的にロードするか、java -cp.

OK、私は問題を理解し始めています。他の誰かのプロジェクトで一連のテストを実行しようとしていますが、テストが他の依存関係を参照している場合は機能しません。簡単に言えば、これは難しいです。外部プロジェクトの参照されたクラス/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 コンテナーなどのコンテナーへの参照が含まれています。これがプロジェクトで達成可能であると思われる場合、これはこれを達成するための 1 つの方法かもしれません。はるかに良い方法は、maven などの使用を強制することです。そうすれば、次のようにテストを実行できます。

$ mvn test

jenkins の下でプロジェクトを実行およびビルドすると、優れたレポートも得られるという追加のボーナスがあります。

于 2012-03-09T12:54:26.893 に答える