2014-04-07 15 views
1

作为对Java面向对象编程的介绍的一部分,我们进行了大量(20-36小时)的实践练习 - 今年基于Tetris。学生遵循指导说明 - 通过文本描述和uml类图 - 如何实现他们的游戏。连接到本指南是一个运行一套单元测试(使用TestNg编写)的工具,以检查它们的实现是否符合说明。单元测试使用100%符合的代码版本进行预编译,并通过显示测试结果的自定义用户界面启动。执行的测试次数取决于学生已经达到的部分。如何在Java编译时链接Exception类

单元测试类的所有结构以类似的方式:

public static void classExists(String fullClassName) { 
    try { 
     @SuppressWarnings("unused") 
     Class<?> clazz = Class.forName(fullClassName); 
    } catch (ClassNotFoundException cnfe) { 
     fail(fullClassName + " could not be found on the classpath."); 
    } 
} 
  1. 测试类存在

  2. 如果(1)成功:测试类能见度

  3. 如果(2)成功:测试方法/属性存在

  4. 如果(3)成功:测试的方法的功能

这非常适用,除了延伸异常,如果当我们要测试的一类(4),我们写出:

BloxException be = new BloxException("Message",value); 

测试按预期工作,特别是如果BloxException不存在,测试(1)失败,其他检查不执行,但是,如果我们试图抛出异常:

throw new BloxException("Message", value); 

测试是n没有执行,因为TestNg找不到类BloxException。 我们推测这是由于Java如何编译上面的两行,任何人都可以告诉我为什么抛出异常时我们需要该类,但是如果我们创建一个新的异常,我们不需要代码来执行测试?

这里是异常堆栈跟踪仅使用throw新BloxException时出现:

java.lang.NoClassDefFoundError: fr/eseo/blox/model/BloxException 
at java.lang.Class.getDeclaredMethods0(Native Method) 
at java.lang.Class.privateGetDeclaredMethods(Class.java:2436) 
at java.lang.Class.privateGetPublicMethods(Class.java:2556) 
at java.lang.Class.getMethods(Class.java:1412) 
at org.testng.internal.TestNGClassFinder.<init>(TestNGClassFinder.java:59) 
at org.testng.TestRunner.initMethods(TestRunner.java:409) 
at org.testng.TestRunner.init(TestRunner.java:235) 
at org.testng.TestRunner.init(TestRunner.java:205) 
at org.testng.TestRunner.<init>(TestRunner.java:153) 
at org.testng.SuiteRunner$DefaultTestRunnerFactory.newTestRunner(SuiteRunner.java:522) 
at org.testng.SuiteRunner.init(SuiteRunner.java:157) 
at org.testng.SuiteRunner.<init>(SuiteRunner.java:111) 
at org.testng.TestNG.createSuiteRunner(TestNG.java:1273) 
at org.testng.TestNG.createSuiteRunners(TestNG.java:1260) 
at org.testng.TestNG.runSuitesLocally(TestNG.java:1114) 
at org.testng.TestNG.run(TestNG.java:1031) 
at fr.eseo.ac20.core.validation.runners.Validator.<init>(Validator.java:131) 
at fr.eseo.ac20.core.validation.runners.CustomValidator.<init>(CustomValidator.java:21) 
at fr.eseo.ac20.core.validation.runners.CustomValidator.main(CustomValidator.java:17) 
Caused by: java.lang.ClassNotFoundException: fr.eseo.blox.model.BloxException 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
    ... 19 more 

这样的帮助,我已经创建了两个简单的测试案例显示是怎么回事,他们都可以从下载examples.zip。解压缩文件,并从命令行变化到tng_good文件夹,并执行

java -cp testng-6.0.1.jar:. org.testng.TestNG tng.xml 

然后改变到tng_bad文件夹,并执行相同的

java -cp testng-6.0.1.jar:. org.testng.TestNG tng.xml 

第一执行时,与存在测试失败,第二给出了例外。 (测试方法的代码源位于示例子文件夹内)

+3

这大多是没有意义的。无论是否抛出异常,您都有完全相同的*实例创建表达式*,无论上下文如何,其计算结果都完全相同。 –

+0

向我们展示来自TestNg的堆栈跟踪,显示您正在讨论的行为。 –

+0

我不认为这是例外情况。你确定类文件是否在正确的位置,并且名称在需要的地方正确输入? – user2357112

回答

0

这与此例外无关。这里的问题是你加载代码的方式。

在第一种情况下,你叫

Class.forName(fullClassName); 

一类是不可用的,你会得到一个ClassNotFoundException,类就不会被加载。

在第二种情况下,TestNG TestRunner类已加载一个类,依赖于另一个不可用的类。然后稍后尝试获取方法的类型信息......并且由于缺少依赖关系而失败。由于JVM现在已经告诉应用程序有关缺少依赖关系的类,因此现在它处于该类被“破坏”的状态。因此,它抛出了不同的例外NoClassDefFoundError


基本上,您的加载和单独测试类的想法不能工作。当你加载一个类时,它所依赖的任何类(包括它所抛出的任何异常)需要用于加载......否则你将得到异常。

他们不应该运行它,但学生是学生,他们有时会尝试运行所有的测试,即使他们没有完成该部分。

简单。向他们解释,如果他们这样做,它将无法工作:-)

+0

我想同意你的看法,但我现在通过链接添加了一个示例(请参阅我编辑的第一篇文章),一个测试按预期执行,Class.forName(...)正确地说该类不存在,但是当引发异常时,测试将不会执行。 –