我有一个用JUnit4语法编写的测试类,可以使用“run as junit test”选项在eclipse中运行而不会失败。当我通过蚂蚁目标运行相同的测试时,我收到此错误:
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)
我在课堂上没有公开的arg构造函数,但这真的有必要吗?
这是我的蚂蚁目标
<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>
测试类没有构造函数,但它有一个带有默认修饰符的内部类。它也有一个匿名内部类。两个内部类都给出了“测试类应该具有公共零参数构造函数错误”。我正在使用Ant版本1.7.1和JUnit 4.7
答案 0 :(得分:8)
我相信你需要一个no-args构造函数,但如果你没有声明任何构造函数,Java将为你创建一个合成构造函数。你确定蚂蚁任务没有进入另一个班级;恰好遵循您设置的命名约定(*Test
或Test*
)?
答案 1 :(得分:5)
您必须拥有测试用例的默认构造函数。否则,跑步者不知道如何实例化该类。看起来你有一个带args的构造函数。如果您已经有一个构造函数,Java不会创建默认构造函数。
通常,您应该避免在测试用例中使用构造函数。如果要进行初始化,请编写init方法并使用@BeforeClass进行注释。好处是,如果您有任何错误,堆栈跟踪将更加清晰。正如您所看到的,构造函数的堆栈跟踪对于大多数人来说确实令人困惑。
答案 2 :(得分:5)
Eclipse使用不同的实现来执行JUnit4测试用例 - 它有自己的测试运行器。这恰好与Ant使用的不同 - 在JUnit发行版中可用的默认版本,并且是Ant和Eclipse中环境执行行为中出现差异的原因。
看一下JUnit 4.3.1,4.5和4.7的源代码(特别是testrunners的源代码),我们发现测试类必须有一个公共的零参数构造函数。请注意,JUnit v4.7中的默认运行程序为BlockJUnit4ClassRunner。您会注意到javadocs(真可惜!)包含了构成格式良好的测试类的规则 - 公共零参数构造函数就是其中之一。
答案 3 :(得分:3)
谢谢大家的时间和答案。 我现在找到了解决方案。以前我认为我的ant目标的batchtest部分的输入应该是.class文件,但也可以使用.java文件。
解决了这个问题。现在它不再抱怨缺少公共构造函数的内部类。
<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>
我现在唯一的问题是,我必须在没有测试的情况下过滤掉测试类,以避免“没有可运行的方法” - 错误。也就是helper和util类。
必须有比我更优雅的解决方案。一种解决方案可以是建议[JUnit: how to avoid "no runnable methods" in test utils classes。
的命名约定帮助程序类不包含@Test注释。必须有可能以某种方式利用它......
答案 4 :(得分:1)
您的测试类的实例需要以某种方式进行。您可以创建一个无参数测试,添加以其他方式创建的测试实例,这对于参数化测试非常有用(或者无论如何都在JUnit 3中)。
但是为什么要压制合成的无参数构造函数?
答案 5 :(得分:1)
使用no-arg构造函数可以将测试类聚合到套件中:
TestSuite suite = new TestSuite();
suite.add(TestClass.class);
...
答案 6 :(得分:1)
对于旧版本的junit,如果您的内部类中有单词“Test”,则会出现此问题。
我们在实现子类for-test模式时遇到了这个问题,命名了子类,例如FooForTest。通过重命名为FooSubclass,问题得以解决。
请参阅@Vineet Reynolds的上述评论,了解有关受影响的junit版本的详细信息,以及为什么会出现这种情况,而不是eclipse。
希望有所帮助!
答案 7 :(得分:0)
非静态内部类有一个隐藏的构造函数,它将外部类作为参数。如果你的内部类不与外部类共享状态,只需将它们设为static
。
答案 8 :(得分:0)
可能是因为您使用的是Enclosed.class,所以封闭的类必须是静态
@RunWith(Enclosed.class)
public class MyClassThatCointaintTestClasses {
public static class Class1Test {
@Test
public void test1(){
}
@Test
public void test2(){
}
}
public static class Class2Test {
@Test
public void test21(){
}
@Test
public void test22(){
}
}
}