多模块 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 路径?的主要内容,如果未能解决你的问题,请参考以下文章