【问题标题】:Wrap multiline String for Junit Testing为 Junit 测试包装多行字符串
【发布时间】:2012-10-16 14:49:38
【问题描述】:

为了比较 JUnit 测试中的多行文本结果,我经常需要从文本表示 使用多行文本初始化字符串的 Java 代码。

例如如果测试应该检查包含以下内容的 xml 字符串:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Customer>
    <id>100</id>
    <name>John Doe</name>
    <orders>
        <Order>
            <address>100 main street, smalltown, pa</address>
            <orderid>1100</orderid>
        </Order>
        <Order>
            <address>5 broadway, ny, ny</address>
            <orderid>1200</orderid>
        </Order>
    </orders>
</Customer>

我想使用一个工具/生成器来接受上述输入并得到以下结果:

String expected ="";
    expected+="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
expected+="<Customer>\n";
expected+="    <id>100</id>\n";
expected+="    <name>John Doe</name>\n";
expected+="    <orders>\n";
expected+="        <Order>\n";
expected+="            <address>100 main street, smalltown, pa</address>\n";
expected+="            <orderid>1100</orderid>\n";
expected+="        </Order>\n";
expected+="        <Order>\n";
expected+="            <address>5 broadway, ny, ny</address>\n";
expected+="            <orderid>1200</orderid>\n";
expected+="        </Order>\n";
expected+="    </orders>\n";
expected+="</Customer>\n";

和/或

    // Create test file
    java.io.PrintWriter srcWriter = new java.io.PrintWriter(new java.io.FileOutputStream(testFile));
    srcWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
    srcWriter.println("<Customer>\n");
    srcWriter.println("    <id>100</id>\n");
    srcWriter.println("    <name>John Doe</name>\n");
    srcWriter.println("    <orders>\n");
    srcWriter.println("        <Order>\n");
    srcWriter.println("            <address>100 main street, smalltown, pa</address>\n");
    srcWriter.println("            <orderid>1100</orderid>\n");
    srcWriter.println("        </Order>\n");
    srcWriter.println("        <Order>\n");
    srcWriter.println("            <address>5 broadway, ny, ny</address>\n");
    srcWriter.println("            <orderid>1200</orderid>\n");
    srcWriter.println("        </Order>\n");
    srcWriter.println("    </orders>\n");
    srcWriter.println("</Customer>\n");
    srcWriter.close();
    // PrintWriter never throws Exceptions, one must check the error state manually
    //
    if (srcWriter.checkError())
    {
        throw new IOException( "can not write " + testFile );
    }   

什么是开发工具/eclipse 实用程序或插件来实现这一点?

  • 从文件中获取多行输入文本(在 IDE 或命令行中)
  • 转义引号和反斜杠
  • 转换为初始化字符串文字和/或将在 Java 代码中创建文件而不需要额外文件资源的 Java 代码
  • 将结果输出到新文件和/或控制台或直接输出到编辑器以在编译时使用

输出文件(如果有)不应与编译结果一起提供。在文件模式下,输入文件的等效项应该从 java 代码中的字符串文字重新创建。

【问题讨论】:

  • 您上面的两种解决方案都不起作用怎么办?目前还不清楚是什么问题,你能澄清一下吗?
  • 我正在寻找一种将多行文本转换为代码的工具,这样我就不必一遍又一遍地手动执行此操作。
  • 如果你有一个字符串对象作为输入,你只需将它写入一个文件(不需要转义)。而且,如果您读入包含引号或其他特殊字符的文件,则再次不需要“转义”。仅当在 Java 代码中输入字符串文字为 String xyz = "sfdsf" 时才需要转义字符,而不是在使用 String 实例时。
  • “多行文本转代码”是什么意思?我假设您没有尝试将此字符串编译为 Java 字节码。
  • 我已经稍微修改了这个问题,以澄清我真的希望在 java 代码中创建字符串和文件,而不是在单独的资源中

标签: java eclipse junit


【解决方案1】:

假设您从另一个来源复制多行文本,并且您使用的是 Eclipse,它可以自动将您的文本转换为多行字符串文字。

在我的版本中,在 Windows -> Preferences -> Java -> Editor -> Typing -> Escape text when paste into a String literal 下启用它

如果你输入

String expected = "

并复制一些文本,例如

blah
blah
blah
blah
blah

然后粘贴你的字符串,Eclipse 会创建:

 String expected = "blah\n" + 
 "blah\n" + 
 "blah\n" + 
 "blah\n" + 
 "blah"

我个人认为如果 Java 有一个与 Perl 的 HERE 文档等效的多行文档会很好。

【讨论】:

  • 非常好 - 我明天必须投票并接受,因为我的投票配额今天用完了
  • 省去了很多挫折。谢谢!
【解决方案2】:

为什么不直接将您的 XML 存储在一个单独的文件中,然后使用 Apache Commons 将其读入字符串?

String fileName = "path/to/your/file";
String fileText = FileUtils.readFileToString(new File(fileName));

有关 FileUtils 的信息 - https://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html

【讨论】:

  • 我不想在编译时使用外部文件。在运行时它们没问题。
  • 我不确定我是否看到您的问题的区别,但如果是这种情况,我建议您考虑编辑问题以删除提到“从文件中获取多行输入文本”的项目符号.
  • 顺便说一句-根据您的编辑,我仍然建议将此作为可能的解决方案。文件本身可以位于您的源代码树中,该位置不必位于项目外部或文件系统中的其他位置。这只是归结为您希望如何构建项目;我已经看到使用“资源”包来存储文件等用于单元测试等的约定......
【解决方案3】:

在我看来,这似乎是一个失败。基本上,您想针对带有操作系统特定换行符的漂亮打印的 XML 进行测试。

您不能简单地编写一些简单的访问者模式,跨越生成的和预期的 XML 来验证一切是否符合预期?通过这种方式,您还可以避免预期和生成的 XML 无效的问题。

另外,假设命名空间声明按顺序更改或属性按顺序更改:XML 在语义上是等效的,但在语法上是不同的。这个应该怎么处理?这是一次失败的测试吗?在我看来,这是一个通行证。

【讨论】:

  • xml 只是一个例子。任何多行字符串都可以作为输入。
  • 我想你可能还是会遇到换行问题。
【解决方案4】:

对于非 Eclipse 用户,以下脚本解决方案可能会有所帮助:

#!/bin/bash
#
#   Copyright (C) 2012 BITPlan GmbH (http://www.bitplan.com)
# 
#   Author: Wolfgang Fahl
#
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.


#
# wrap code for use in JUnit Test cases
#
wrapJUnit() {
  file=$1
  mode=$2
  echo "wrapping $file with mode $mode"
  cat $file | gawk -v mode="$mode" '

# check mode and add header if mode is file
BEGIN {
  if (mode=="file") {
        print " // Create test file"
        print " java.io.PrintWriter srcWriter = new java.io.PrintWriter(new java.io.FileOutputStream(testFile));"
    }   
}
# work on each line
{
    line=$0
    # replace a single \ with \\
    gsub("\\","\\\\",line)
    # replace a quote with \ quote
    gsub("\"","\\\"",line)
    # output the modified line
    if (mode=="file") {
        print " srcWriter.println(\"" line "\\n\");"
    } else {
        if (more++) {
            print " expected+=\"" line "\\n\";" 
        } else {
            print " expected =\"" line "\\n\";" 
        }   
    }   
}

END {
  if (mode=="file") {
        print " srcWriter.close();"
        print " // PrintWriter never throws Exceptions, one must check the error state manually"
        print " //"
        print " if (srcWriter.checkError())"
        print " {"
        print "     throw new IOException( \"can not write \" + testFile );"
        print " }   "
    }
}

' > $1.wrap
cat $1.wrap
}

#
#
# show usage
# 
usage() {
    echo "usage: wrapcode inputfile [simple]"
    echo "  will take the text and prepare it for JUnit usage as a string";
    exit 1
}

#
# check number of command line parameters
#
if [ $# -lt 1 ]
then
  usage
fi

file=$1

if [ $# -lt 2 ]
then
  wrapJUnit $file file
else
  wrapJUnit $file string
fi

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    相关资源
    最近更新 更多