11 Stimmen

Benötigen JUnit4-Testklassen einen öffentlichen no arg-Konstruktor?

Ich habe eine Testklasse, die in JUnit4-Syntax geschrieben ist und in Eclipse mit der Option "run as junit test" ausgeführt werden kann, ohne zu scheitern. Wenn ich denselben Test über ein Ant-Target ausführe, erhalte ich diesen Fehler:

java.lang.Exception: Test class should have public zero-argument constructor
at org.junit.internal.runners.MethodValidator.validateNoArgConstructor(MethodValidator.java:54)
at org.junit.internal.runners.MethodValidator.validateAllMethods(MethodValidator.java:39)
at org.junit.internal.runners.TestClassRunner.validate(TestClassRunner.java:33)
at org.junit.internal.runners.TestClassRunner.<init>(TestClassRunner.java:27)
at org.junit.internal.runners.TestClassRunner.<init>(TestClassRunner.java:20)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
at junit.framework.JUnit4TestAdapter.<init>(JUnit4TestAdapter.java:24)
at junit.framework.JUnit4TestAdapter.<init>(JUnit4TestAdapter.java:17)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:386)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:911)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:768)
Caused by: java.lang.NoSuchMethodException: dk.gensam.gaia.business.bonusregulering.TestBonusregulerAftale$Test1Reader.<init>()
at java.lang.Class.getConstructor0(Class.java:2706)
at java.lang.Class.getConstructor(Class.java:1657)
at org.junit.internal.runners.MethodValidator.validateNoArgConstructor(MethodValidator.java:52)

Ich habe keinen öffentlichen no arg-Konstruktor in der Klasse, aber ist das wirklich notwendig?

Das ist mein Ameisen-Ziel

<target name="junit" description="Execute unit tests" depends="compile, jar-test">
        <delete dir="tmp/rawtestoutput"/>
        <delete dir="test-reports"/>
        <mkdir dir="tmp/rawtestoutput"/>
        <junit printsummary="true" failureproperty="junit.failure" fork="true">
          <classpath refid="class.path.test"/>
          <classpath refid="class.path.model"/>
          <classpath refid="class.path.gui"/>
          <classpath refid="class.path.jfreereport"/>
            <classpath path="tmp/${test.jar}"></classpath>
          <batchtest todir="tmp/rawtestoutput">
            <fileset dir="${build}/test">
                <include name="**/*Test.class" />
                <include name="**/Test*.class" />
            </fileset>
          </batchtest>
        </junit>
        <junitreport todir="tmp">
          <fileset dir="tmp/rawtestoutput"/>
          <report todir="test-reports"/>
        </junitreport>
        <fail if="junit.
failure" message="Unit test(s) failed.  See reports!"/>
    </target>

Die Testklasse hat keine Konstruktoren, aber sie hat eine innere Klasse mit Standardmodifikator. Sie hat auch eine anonyme innere Klasse. Beide inneren Klassen geben den Fehler "Test class should have public zero-argument constructor". Ich verwende Ant Version 1.7.1 und JUnit 4.7

8voto

waxwing Punkte 18142

Ich glaube, Sie brauchen einen no-args-Konstruktor, aber wenn Sie keine Konstruktoren deklarieren, wird Java einen synthetischen für Sie erstellen. Sind Sie sicher, dass die Ant-Task nicht eine andere Klasse aufgreift, die zufällig der von Ihnen festgelegten Namenskonvention folgt ( *Test o Test* )?

5voto

ZZ Coder Punkte 72742

Sie müssen einen Standardkonstruktor für den Testfall haben. Andernfalls weiß der Läufer nicht, wie er die Klasse instanziieren soll. Sieht aus, als hätten Sie einen Konstruktor mit Args. Java erstellt keinen Standardkonstruktor, wenn Sie bereits einen Konstruktor haben.

Im Allgemeinen sollten Sie Konstruktoren in Testfällen vermeiden. Wenn Sie eine Initialisierung durchführen wollen, schreiben Sie eine init-Methode und annotieren Sie sie mit @BeforeClass. Der Vorteil ist, dass der Stack-Trace im Falle eines Fehlers viel sauberer sein wird. Wie Sie sehen können, ist der Stacktrace des Konstruktors für die meisten Leute sehr verwirrend.

5voto

Vineet Reynolds Punkte 74302

Eclipse verwendet eine andere Implementierung zur Ausführung von JUnit4-Testfällen - es hat seinen eigenen Test-Runner. Dieser unterscheidet sich zufälligerweise von dem von Ant verwendeten - dem in der JUnit-Distribution verfügbaren Standard - und ist der Grund für die festgestellte Diskrepanz im Ausführungsverhalten der Umgebungen in Ant und Eclipse.

Ein Blick in den Quellcode von JUnit 4.3.1, 4.5 und 4.7 (insbesondere in den der Testrunner) zeigt, dass Testklassen einen öffentlichen Konstruktor mit Null-Arg haben müssen. Beachten Sie, dass der Standard-Runner in JUnit v4.7 BlockJUnit4ClassRunner . Sie werden feststellen, dass die Javadocs (wie schade!) die Regeln enthalten, die zu befolgen sind, um eine gut geformte Testklasse zu erstellen - ein öffentlicher Konstruktor mit null Argumenten ist eine davon.

3voto

Thomas Baun Punkte 169

Ich danke Ihnen allen für Ihre Zeit und Ihre Antworten. Ich habe jetzt eine Lösung gefunden. Bisher dachte ich, dass die Eingabe für den Batchtest-Teil meines Ant-Targets .class-Dateien sein sollten, aber es ist auch möglich, .java-Dateien zu verwenden.

Damit ist das Problem gelöst. Jetzt beschwert es sich nicht mehr über fehlende öffentliche Konstruktoren in inneren Klassen.

<target name="junit" description="Execute unit tests">
 <delete dir="tmp/rawtestoutput"/>
 <delete dir="test-reports"/>
    <mkdir dir="tmp/rawtestoutput"/>     
    <junit printsummary="on" failureproperty="junit.failure" fork="true">
      <jvmarg value="-Duser=TBA -Dpassword=ibber11"/>
        <classpath refid="class.path.test"/>
        <classpath refid="class.path.model"/>
        <classpath refid="class.path.gui"/>
        <classpath refid="class.path.jfreereport"/>
     <classpath path="tmp/${test.jar}"/>
      <batchtest todir="tmp/rawtestoutput">
        <fileset dir="src/test">
            <include name="**/*.java"/>
         <exclude name="**/SessionHelper.java"/>
         <exclude name="**/TestHelper.java"/>
        </fileset>
      </batchtest>
     <sysproperty key="user" value="tba"/>
     <sysproperty key="password" value="ibber11"/>
    </junit>
    <junitreport todir="tmp">
      <fileset dir="tmp/rawtestoutput"/>
      <report todir="test-reports"/>
    </junitreport>
    <fail if="junit.failure" message="Unit test(s) failed.  See reports!"/>
</target>

Mein einziges Problem ist nun, dass ich die Testklassen ohne Tests herausfiltern muss, um einen "No runnable methods"-Fehler zu vermeiden. Das heißt, die helper und util Klassen.

Es muss eine elegantere Lösung als meine geben. Eine Lösung könnte eine Benennungskonvention sein, wie sie in [ JUnit: Wie vermeidet man "no runnable methods" in Test-Utilitys Klassen .

Die Hilfsklassen enthalten nicht die @Test-Anmerkung. Es muss doch möglich sein, dies auf irgendeine Weise zu nutzen...

1voto

Tom Hawtin - tackline Punkte 142461

Die Instanzen Ihrer Testklassen müssen irgendwie erstellt werden. Sie können einen no-arg-Test erstellen, der auf andere Weise erstellte Testinstanzen hinzufügt. Dies kann für die Parametrisierung von Tests nützlich sein (oder war es zumindest in JUnit 3).

Aber warum sollte man den synthetischen no-arg-Konstruktor unterdrücken?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X