I have a test class, written in JUnit4 syntax, that can be run in eclipse with the "run as junit test" option without failing. When I run the same test via an ant target I get this error:
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)
I have no public no arg constructor in the class, but is this really necessary?
This is my ant target
<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>
The test class have no constructors, but it has an inner class with default modifier. It also have an anonymouse inner class. Both inner classes gives the "Test class should have public zero-argument constructor error". I am using Ant version 1.7.1 and JUnit 4.7
Thank you all for your time and your answers. I have now found a solution. Previously I thought the input for the batchtest part of my ant target should be .class files but it is also possible to use .java files.
That solved the problem. Now it no longer complains about inner classes missing public constructors.
My only problem now is, that I have to filter out the test classes without tests, in order to avoid a "No runnable methods"-error. That is, the helper and util classes.
There must be a more elegant solution than mine. One solution could be a naming convention as suggested [JUnit: how to avoid "no runnable methods" in test utils classes.
The helper classes does not contain the @Test annotaion. It must be possible to utilize this in some way...
You must have a default constructor for the test case. Otherwise, the runner doesn't know how to instantiate the class. Looks like you have a constructor with args. Java doesn't create default constructor if you already have a constructor.
Generally, you should avoid constructors in test cases. If you want do initialization, write a init method and annotate it with @BeforeClass. The benefit is that the stack trace will be much cleaner if you have any errors. As you can see, the constructor's stack trace is really confusing for most people.
Eclipse uses a different implementation to execute JUnit4 test cases - it has its own test runner. This happens to be different from the one used by the Ant - the default one available in the JUnit distribution, and is the reason for the discrepancy noted in the execution behavior of the environments in Ant and Eclipse.
Taking a look at the source code of JUnit 4.3.1, 4.5 and 4.7 (especially that of the testrunners) reveals that test classes must have a public zero-arg constructor. Do note that the default runner in JUnit v4.7 is BlockJUnit4ClassRunner. You'll notice that the javadocs (what a pity!) contain the rules to be followed on what constitutes a well formed test class - a public zero-argument constructor is one of them.
Instances of your test classes need to be made somehow. You can create a no-arg test which adds test instances created in some other way, which can be useful for parameterising tests (or was in JUnit 3, anyway).
But why would you suppress the synthetic no-arg constructor?
Could be because you are using Enclosed.class, then the enclosed classes has to be static
}
Having a no-arg constructor allows test classes to be aggregated into suites: