Java 输出为文本墙时的单元测试

Java 输出为文本墙时的单元测试,java,unit-testing,testing,Java,Unit Testing,Testing,我目前正在测试我的应用程序的一部分(我们假设它是一个名为X)它以反射java方法作为参数,并将基于它打印一些java代码(也就是说,它是一个代码生成器)。例如,将String.toString()传递到X时,呈现的字符串输出将是: public static java.lang.String toString(String thisObj, boolean isMonitoring) { String thisObjOld = (String)thisObj.clone(thisObj,

我目前正在测试我的应用程序的一部分(我们假设它是一个名为
X
)它以反射java方法作为参数,并将基于它打印一些java代码(也就是说,它是一个代码生成器)。例如,将
String.toString()
传递到
X
时,呈现的字符串输出将是:

public static java.lang.String toString(String thisObj, boolean isMonitoring) {
    String thisObjOld = (String)thisObj.clone(thisObj, false);

    if (isMonitoring) {
        toStringPre(thisObj);
    }

    java.lang.String result = thisObj.toString_Original();

    if (isMonitoring) {
        toStringPost(thisObj, thisObjOld, result);
    }

    return result
}
现在,我想知道如何测试这个输出。我想(单独)测试不同的东西

我知道最好的做法是在印刷之前,而不是在最终文本之前,对抽象表示进行断言。但不幸的是,这似乎是太多的工作设置

我希望测试的示例有:

  • 如果返回类型正确(
    java.lang.String
  • 如果方法的名称正确(
    toString
    ),以及它的参数`(String thisObj,boolean isMonitoring)

如何更好地处理这个问题?使用正则表达式?使用
String.split()

例如,junit示例:

public void testX(){
   X gnerator = new X(getTestMethodObject());
   Assert.assertEquals(StringUtils.readFully(new File("expected_output.txt")), generator.generate());
}
显然,这将执行字符串比较,当生成的内容更改时,您必须手工编写新的预期输出。因此,虽然这很简单,但以后可能会成为维护的噩梦

当然,另一种方法是对生成的输出进行lex处理,并检查生成的令牌(我假设您实际上无法在测试环境中编译生成的代码)。比如说,这是一个非常简单的lexor(我不担保——我只是在谷歌搜索了几分钟后发现了它……但它已经找到了,所以我认为它是好的?)。或者,在测试中使用一些可能是多余的东西


我个人坚持将手写的预期输出与生成的输出进行比较。它的关键性要低得多,而且比使用成熟的词法分析器更容易发现错误。

为什么不1)编译生成的代码并使用反射来断言“语义”,或者,如果由于依赖关系和其他原因无法编译和加载,2)使用JAVA解析器创建一个抽象语法树,您可以遍历并进行断言。(例如,该项目有JAVA 6的语法)。

编译生成代码怎么样?测试代码的语法是否正确

然后使用反射检查名称、参数和返回类型


然后在模拟环境中运行它,检查它是否执行了它应该执行的操作。

如果输出是代码,您能否测试生成的代码是否正确运行?理论上是,但实际上不是。为了让它发挥作用,我还有很多其他方法没有在这里列出。你能解释一下为什么要测试这些东西吗?这个生成的代码不是在什么地方使用的吗?如果您使用编译器,它会检查这些内容…编译器不会检查代码的语义是否正确。生成的代码将在其他地方使用,但会在WAAAAAY复杂环境中使用。另外,我将在几个月内运行整个程序,我不想等待它进行测试!问题是,这样我将不得不编写比我特别想要测试的代码多得多的代码。如果没有更好的方法,我会使用这种方法,但在我看来,甚至regex也可能是比普通的旧字符串比较更好的选择。我想regex是lex java代码的一种方法——毕竟,lexer只是一个非常复杂的状态机,与regex没有什么不同。我认为字符串比较会更容易,因为您可以连续使用X类生成的输出的早期版本的输出作为测试,并在添加时手动编辑中的新更改。这个问题经常发生在测试REST api的过程中,我发现这个解决方案是最简单的,也最不麻烦一些,因为它提供了大量的“好”信息。我不知道什么时候可以使用完整的.java文件,所以编译它不是一个选项。