2009-09-20 96 views
11

我有一個用JUnit4語法編寫的測試類,它可以在eclipse中運行,並且運行「junit測試」選項而不失敗。當我通過Ant目標運行相同的測試,我得到這個錯誤:JUnit4測試類是否需要公共無參數構造函數?

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) 

我沒有公開在類無參數的構造函數,但是這真的有必要嗎?

這是我的Ant目標

<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> 

測試類沒有構造函數,但它與默認的修飾符的內部類。它也有一個anonymouse內部類。兩個內部類都給出了「測試類應該有公共零參數構造函數錯誤」。我使用的Ant版本1.7.1和JUnit測試類4.7

回答

3

謝謝大家的時間和你的答案。 我現在已經找到了解決方案。以前我認爲我的ant target的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註釋。它必須可以以某種方式使用它...

+0

嘗試排除**/* Helper.java。 – 2009-09-30 13:55:54

1

實例需要以某種方式作出。您可以創建一個無參數測試,它添加以某種其他方式創建的測試實例,這對於參數化測試(或者在JUnit 3中,無論如何)都是有用的。

但是,爲什麼你會抑制合成的無參數的構造函數?

1

有一個無參數的構造函數允許測試類聚合成套房:

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

我相信你需要一個無參數的構造函數,但是如果你不聲明任何構造函數Java將創建一個合成一個給你。你確定這個螞蟻任務沒有拿起另一個班級嗎?一個恰好按照您設定的命名約定(*TestTest*)?

5

您必須具有測試用例的默認構造函數。否則,跑步者不知道如何實例化該類。看起來你有一個帶參數的構造函數。如果你已經有一個構造函數,Java不會創建默認構造函數。

一般情況下,應避免在測試用例的構造函數。如果你想做初始化,寫一個init方法並用@BeforeClass註釋它。好處是,如果您有任何錯誤,堆棧跟蹤將會更清晰。正如你所看到的,構造函數的堆棧跟蹤對於大多數人來說確實令人困惑。

5

Eclipse使用不同的實現來執行JUnit4測試用例 - 它有自己的測試運行。這恰好與Ant所使用的不同 - 它是JUnit發行版中默認的一個,並且是Ant和Eclipse中環境的執行行爲中出現差異的原因。

考慮看看的JUnit 4.3.1,4.5和4.7的源代碼(尤其是在testrunners的)揭示了測試類必須有一個公共的零參數構造函數。請注意,JUnit v4.7中的默認運行器是BlockJUnit4ClassRunner。你會注意到,javadocs(很遺憾!)包含了關於什麼構成了一個良構的測試類的規則 - 一個公共的零參數構造函數就是其中之一。

+0

我想和你一樣。這與junit3 vs junit4有關,但就我在堆棧跟蹤中看到的,它實際上是一個涉及的JUnit4TestAdapter。 – 2009-09-20 19:57:52

+0

那麼,我確實看看了Ant 1.7.1的來源。在JUnitTestRunner.java(出現在堆棧跟蹤中的第386行)中,只有滿足前提條件時纔會創建TestSuite實例。 – 2009-09-20 20:09:25

+0

糟糕,第396行創建了TestSuite,而386創建了JUnit4TestAdapter。 – 2009-09-20 20:11:42

0

非靜態內部類有一個隱藏的構造函數,它將外部類作爲參數。如果你的內部類沒有與外部類共享狀態,只需讓他們static

1

對於舊版本的junit,如果在內部類中有「Test」一詞,則會出現此問題。

我們遇到了這個問題,同時實現了子類測試模式,命名子類,例如FooForTest。通過重命名爲FooSubclass,問題解決了。

有關受影響的junit版本的更多詳細信息,請參閱@Vineet Reynolds的上述評論,以及爲什麼發生這種情況的原因是螞蟻但不是蝕。

希望有幫助!

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

}

相關問題