【问题标题】:Does JUnit4 testclasses require a public no arg constructor?JUnit4 测试类是否需要公共无参数构造函数?
【发布时间】:2009-09-20 17:20:24
【问题描述】:

我有一个用 JUnit4 语法编写的测试类,它可以在 eclipse 中使用“run as junit test”选项运行而不会失败。当我通过 ant 目标运行相同的测试时,出现此错误:

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)

我在类中没有 public no 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

【问题讨论】:

    标签: java ant junit


    【解决方案1】:

    我相信您需要一个无参数构造函数,但如果您不声明任何构造函数,Java 将为您创建一个合成的构造函数。您确定 ant-task 没有选择其他课程吗?恰好遵循您设置的命名约定(*TestTest*)?

    【讨论】:

      【解决方案2】:

      你必须有一个测试用例的默认构造函数。否则,跑步者不知道如何实例化该类。看起来你有一个带 args 的构造函数。如果您已经有构造函数,Java 不会创建默认构造函数。

      通常,您应该避免在测试用例中使用构造函数。如果要进行初始化,请编写一个 init 方法并使用 @BeforeClass 对其进行注释。好处是如果您有任何错误,堆栈跟踪将更加清晰。如您所见,构造函数的堆栈跟踪对于大多数人来说确实令人困惑。

      【讨论】:

        【解决方案3】:

        Eclipse 使用不同的实现来执行 JUnit4 测试用例 - 它有自己的测试运行器。这恰好与 Ant 使用的不同——JUnit 发行版中的默认版本,这也是 Ant 和 Eclipse 中环境的执行行为出现差异的原因。

        查看 JUnit 4.3.1、4.5 和 4.7(尤其是 testrunners)的源代码会发现,测试类必须有一个公共的零参数构造函数。请注意,JUnit v4.7 中的默认运行器是BlockJUnit4ClassRunner。您会注意到 javadocs(真可惜!)包含构成格式良好的测试类要遵循的规则 - 公共零参数构造函数就是其中之一。

        【讨论】:

        • 我的想法和你一样。它与junit3 vs junit4有关,但据我在stacktrace中看到的,它实际上是一个涉及的JUnit4TestAdapter。
        • 嗯,我确实看过 Ant 1.7.1 的源代码。在 JUnitTestRunner.java(出现在堆栈跟踪中的第 386 行)中,仅当满足先决条件时才会创建一个 TestSuite 实例。
        • 糟糕,第 396 行创建了 TestSuite,而第 386 行创建了 JUnit4TestAdapter。
        • @Thomas,您使用的是哪个版本的 JUnit 和 Ant?原因与堆栈跟踪中存在 TestRunner 类本身有关。
        • 我正在使用 TeamCity,并且捆绑的版本是 1.7.1。 Junit 版本是 4.7。这是我在目标下的类路径中指定的版本。我试图在 Eclipse 中运行相同的 ant 目标和与上面相同的版本。同样的错误。
        【解决方案4】:

        感谢大家的宝贵时间和回答。 我现在找到了解决方案。以前我认为我的 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 注释。一定有可能以某种方式利用它......

        【讨论】:

          【解决方案5】:

          您的测试类的实例需要以某种方式制作。您可以创建一个无参数测试,它添加以其他方式创建的测试实例,这对于参数化测试很有用(或者在 JUnit 3 中,无论如何)。

          但是你为什么要禁止合成无参数构造函数呢?

          【讨论】:

            【解决方案6】:

            拥有无参数构造函数允许将测试类聚合到套件中:

             TestSuite suite = new TestSuite();
             suite.add(TestClass.class);
             ...
            

            【讨论】:

              【解决方案7】:

              对于旧版本的junit,如果你的内部类中有“Test”这个词,就会出现这个问题。

              我们在实现 subclass-for-test 模式时遇到了这个问题,命名子类,例如,FooForTest。通过重命名为FooSubclass,问题就解决了。

              请参阅@Vineet Reynolds 的上述评论,了解有关受影响的 junit 版本的更多详细信息,以及为什么会在 ant 而不是 eclipse 上发生这种情况。

              希望有帮助!

              【讨论】:

                【解决方案8】:

                非静态内部类有一个隐藏的构造函数,它将外部类作为参数。如果您的内部类不与外部类共享状态,只需将它们设为static

                【讨论】:

                  【解决方案9】:

                  可能是因为你使用的是Enclosed.class,那么封闭的类必须是static

                  @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(){
                  }
                  }
                  

                  }

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-10-25
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-05-08
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-04-23
                    相关资源
                    最近更新 更多