多模块 Java/Maven 项目中 DBUnit 的 XML DTD 路径?

Posted

技术标签:

【中文标题】多模块 Java/Maven 项目中 DBUnit 的 XML DTD 路径?【英文标题】:Path to XML DTD for DBUnit in multi-module Java/Maven project? 【发布时间】:2011-03-02 08:41:09 【问题描述】:

我有一个多模块 Maven 项目。在持久模块中,我有许多引用 DTD 的 XML 文件数据文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "myapp-data.dtd" >

<dataset>
      .....omitted for brevity....
</dataset>

DTD 与 XML 文件存储在同一目录中,甚至 Eclipse 也将这些 XML 文件报告为有效。

但是,当我运行应用程序时,DBUnit FlatXMLDataSet 会抛出 FileNotFound 异常,因为它无法定位 DTD。它显然是在根项目目录(例如 myproject/)中寻找 DTD。我原以为它会在与 XML 文件本身相同的目录中查找 DTD(例如 myproject/persist/target/test-data)。

查看 DBUnit 源代码,它有这样的说法“相对 DOCTYPE uri 是从当前工作目录中解析的。”

有什么好的方法可以解决这个问题?

【问题讨论】:

【参考方案1】:

好的,我想我想通了。谢天谢地开源。

FlatXmlDataSetBuilder 上有一个方法可以将流传输到 DTD。这是一个公共方法 IMO 真是太疯狂了,但话说回来,DBUnit 与 dtd 文件的 XML 不在同一个目录中,这太疯狂了。所以这里是:

String dtdResourceName = "classpath:test-data/myapp-data.dtd";      
Resource res = applicationContext.getResource(dtdResourceName);
builder.setMetaDataSetFromDtd(res.getInputStream());

现在我将带有 dtd 的 DOCTYPE 声明留在与 XML 相同的目录中,并使用此 hack 来欺骗 DBUnit 做正确的事情。

【讨论】:

你用的是什么版本?我在这里找不到此代码:dbunit.sourceforge.net/xref/org/dbunit/dataset/xml/… 它在您提供的链接中...检查第 195 行——实际上很难找到。 dbunit.sourceforge.net/xref/org/dbunit/dataset/xml/…【参考方案2】:

始终使用正确的变量来访问特殊目录,因为多模块构建与本地构建具有不同的工作目录:

所以

而不是mydir 使用$project.basedir/mydir 而不是target/mydir 使用$project.build.directory/mydir 而不是target/classes/mydir 使用$project.build.outputDirectory/mydir

无论从何处调用,这些变量始终计算为当前项目。这是Overview of POM variables(不完整,但最重要的东西在里面)

此外,如果您想进行一些交互式查询式调试,help:evaluate mojo 会派上用场:

打电话

mvn help:evaluate

你会被提示输入一个表达式。如果您输入一个表达式,例如$project.build.plugins[0] ,将列出指定元素的合并dom


编辑:

好的,现在我想我看到了问题所在。那为什么不直接引用xml中的目录:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "target/test-classes/myapp-data.dtd" >

我知道它不漂亮,但它应该可以工作,不管是否是多模块。单元测试的当前目录始终是当前 $project.basedir,而不是父项目目录。

【讨论】:

我认为问题不在于 Maven,而在于 DBUnit。它在 DTD 中寻找错误的位置。还有另一种更好的方法来在 XML 文件中指定它吗?是否有我缺少的 DBUnit 设置? 采用新方法可以很好地解决运行时问题——但现在 Eclipse 抱怨它无法找到要验证的 DTD。我也想吃蛋糕!! “目标”目录仅在 maven 构建后存在。如果我运行 mvn clean 它不存在,然后 Eclipse 又开始抱怨了!我检查了 DBUnit 的源代码,他们真的不遗余力地找不到 dtd....【参考方案3】:

您可以将 DTD 发布到 Web 服务器,然后将其 HTTP URL 放入 DOCTYPE,例如:

<!DOCTYPE myapp-data SYSTEM "-//The Owner//The Description//EN" "http://host/path/to/myapp-data.dtd">

【讨论】:

【参考方案4】:

在打开 XML 文件时尝试使用“File”而不是“FileInputStream”。

例如:

ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new File(fileName)));

这样,DTD 的相对路径应该以 XML 文件的目录开头。

如果你使用

ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new FileInputStream(fileName)));

路径应该是相对于当前工作目录的。

【讨论】:

【参考方案5】:

这涉及一些难看的重复,但您可以将 DTD 的内容粘贴到相关的 XML 文件中,然后将它们用作internal DTDs。

【讨论】:

以上是关于多模块 Java/Maven 项目中 DBUnit 的 XML DTD 路径?的主要内容,如果未能解决你的问题,请参考以下文章

Java--Maven多模块管理

推荐学Java——Maven初识

推荐学Java——Maven初识

推荐学Java——Maven初识

Java+maven项目新建

-Java- Maven命令