2012-10-05 5 views
6

Ich weiß, es gibt viele ähnliche Fragen wie this one, aber nach dem Lesen über die meisten von ihnen scheint ich das gleiche Problem zu haben, aber aus verschiedenen Gründen.Ant JUnit ClassNotFoundException

Ich habe eine <junit> Aufgabe in meinem Ant Build und bekomme eine ClassNotFoundException. In den meisten der ähnlich verwandten Fragen (wie die oben genannten) stellte sich heraus, dass es verschiedene Grade des Autors waren, die den JUnit-Klassenpfad nicht richtig konfigurierten. Obwohl es für mich sehr wahrscheinlich dasselbe ist, hat keiner der Vorschläge zu diesen anderen Fragen für mich funktioniert.

Meine Projekt-Verzeichnisstruktur:

MyProject/ 
    src/main/java/ 
     FakeObject.java 
     ...the rest of my Java main source 
    src/test/java 
     FakeObjectUnitTest.java 
     ...the rest of my Java test source 
    bin/main 
     FakeObject.class 
     ...the rest of main Java binaries 
    bin/test 
     FakeObjectUnitTest.class 
     ...the rest of main Java binaries 
    lib/main 
     ...my main dependencies 
    lib/test 
     junit-4.10.jar 
     hamcrest-1.1.jar 
     ...the rest of my test dependencies 
    gen/reports 
     ...where JUnit should be placing all test reports 
    build/ 
     build.xml 
     build.properties 

In src/test/java/FakeObjectUnitTest.java:

// Package and imports omitted 

public class FakeObjectUnitTest { 
    @Test 
    public void doSomething() { 
     int x = 5; 

     Assert.assertEquals(x, 5); 
    } 
} 

Mein build.xml:

<project name="" basedir=".."> 
    <!-- Main classpath. --> 
    <path id="main.class.path"> 
     <fileset dir="bin/main"/> 
    </path> 

    <!-- Test classpath. --> 
    <path id="test.class.path"> 
     <fileset dir="bin/test"/> 
    </path> 

    <!-- JUnit classpath. --> 
    <path id="junit.class.path"> 
     <fileset dir="lib/main" includes="*.jar"/> 
     <fileset dir="lib/test" includes="*.jar"/> 
     <path refid="main.class.path"/> 
     <path refid="test.class.path"/> 
    </path> 

    <!-- 
     All previous targets omitted for brevity (such as for compiling, etc.), but 
    I assure you all that they work and compile FakeObject.java/FakeObjectUnitTest.java into 
    FakeObject.class/FakeObjectUnitTest.class respectively, and place them in the correct 
bin directories. 
    --> 

    <target name="run-junit" depends="compile"> 

     <property name="junit.path" refid="junit.class.path"/> 
     <echo message="JUnit ClassPath is: ${junit.path}"/> 

     <junit printsummary="yes" haltonerror="yes" haltonfailure="yes"> 
      <classpath refid="junit.class.path"/> 

      <formatter type="xml"/> 

      <batchtest todir="gen/reports"> 
       <fileset dir="src/test/java"> 
        <include name="**/*UnitTest*.java"/> 
       </fileset> 
      </batchtest> 
     </junit> 
    </target> 
</project> 

Wenn ich laufe, dieses Ziel von der Befehlszeile:

run-junit: 
    [echo] Conducting unit tests with JUnit. 
    [echo] JUnit ClassPath is: /<path-to-my-project>/MyProject/lib/test/hamcrest-1.1.jar:/<path-to-my-project>/MyProject/lib/test/junit-4.10.jar:/<path-to-my-project>/MyProject/bin/main/com/myproject/client/FakeObject.class:/<path-to-my-project>/MyProject/bin/test/com/myproject/client/FakeObjectUnitTest.class 
    [junit] Running com.myproject.client.FakeObjectUnitTest 
    [junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 0 sec 

Ich mache dies zu beweisen, dass es FakeObjectUnitTest.class auf dem JUnit Classpath sieht. Es schlägt jedoch mit einem Fehler fehl. Als ich in den XML-TEST-Bericht für diesen Test gehen, sehe ich folgendes:

<error message="com.myproject.client.FakeObjectUnitTest" type="java.lang.ClassNotFoundException">java.lang.ClassNotFoundException: com.myproject.client.FakeObjectUnitTest 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
    at java.lang.Class.forName0(Native Method) 
    at java.lang.Class.forName(Class.java:247) 
</error> 

Wenn ich laufen Ant im ausführlichen Modus (-v) der einzige Hinweis ich sehe, sind eine Reihe von Warnungen entlang der Linien von :

Ignorieren Ausnahme java.util.zip.ZipException: Fehler beim Öffnen Zip-Datei Lese Ressource x

... wo x der Name einer Klassendatei ist.

Ich fand this Frage auf SO, und das Problem stellte sich heraus, dass der Autor Klassen-Dateien zum Klassenpfad hinzugefügt hatte, nicht JARs (was JUnit unglücklich macht). Also habe ich versucht, main.class.path und test.class.path von junit.class/path zu entfernen und dann bekomme ich eine Ausnahme, dass keine der Klassendateien gefunden werden kann.

Irgendwelche Ideen oder Gedanken zu dem, was vor sich geht? Vielen Dank im Voraus und Entschuldigung für die -v Frage hier, aber ich dachte, je mehr Details, desto besser.

Antwort

5

Sie müssen sich für Paket-ähnliche Strukturen verwenden:
From the manual:

Überall dort, wo Pfad artige Werte brauchen zu spezifizieren, kann ein verschachteltes Element verwendet werden. Dies nimmt die allgemeine Form:

<classpath> 
     <pathelement path="${classpath}"/> 
     <pathelement location="lib/helper.jar"/> 
    </classpath> 

So Ihre Lösung aussehen würde:

<!-- JUnit classpath. --> 
<path id="junit.class.path"> 
    <fileset dir="lib/main" includes="*.jar"/> 
    <fileset dir="lib/test" includes="*.jar"/> 
    <pathelement location="bin/main"/> 
    <pathelement location="bin/test"/> 
</path> 
+0

wie üblich, du bist der Mann. Vielen Dank! – IAmYourFaja

2

Ein Blick auf Ihrer Classpath:

...:/<path-to-my-project>/MyProject/bin/main/com/myproject/client/FakeObject.class:... 

Sie keine individuelle Klasse im Klassenpfad so sagen kann.Stattdessen setzen Sie das Verzeichnis, in dem Classpath an der Basis Ihrer Pakethierarchie ist:

...:/<path-to-my-project>/MyProject/bin/main:... 
+0

Dank @Jesper (+1) - aber wenn Sie bemerken, ist der einzige Grund, warum 'FakeObject.class' im JUnit-Klassenpfad ist, weil es das einzige binäre ist, das kompiliert wird. Es befindet sich im Klassenpfad, da es sich innerhalb von 'bin/main' befindet, was ein Teil von' main.class.path' ist, der wiederum ein Teil von 'junit.class.path' ist, also wenn ich etwas nicht vermisse' bin/main ist bereits das Konstrukt, das Teil des JUnit-Klassenpfads ist. – IAmYourFaja

0

make Änderung in Lauf junit Ziel wie folgt

  <batchtest todir="gen/reports"> 
      <fileset dir="bin/tests"> 
       <include name="**/*UnitTest*.class"/> 
      </fileset> 
     </batchtest>