Путь к XML DTD для DBUnit в многомодульном проекте Java / Maven?
У меня есть многомодульный проект maven. В модуле persist у меня есть несколько файлов данных XML-файлов, которые ссылаются на DTD:
<?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. По-видимому, он ищет DTD в корневом каталоге проекта (например, мой проект/). Я ожидал, что он будет искать DTD в том же каталоге, что и сам XML-файл (например, myproject/persist/target/test-data).
глядя на исходный код DBUnit, он должен сказать об этом: "относительный uri DOCTYPE разрешен из текущего рабочего dicrectory."
Как это исправить?
5 ответов
хорошо, я думаю, что понял это. Спасибо за открытый исходный код.
в FlatXmlDataSetBuilder есть метод, который принимает поток в DTD. Это сумасшествие, что это публичный метод IMO, но опять же, это сумасшествие, что DBUnit не выглядит в том же каталоге, что и XML для файла dtd. Вот оно:
String dtdResourceName = "classpath:test-data/myapp-data.dtd";
Resource res = applicationContext.getResource(dtdResourceName);
builder.setMetaDataSetFromDtd(res.getInputStream());
теперь я оставляю объявление DOCTYPE с dtd в том же каталоге, что и XML, и использую этот хак, чтобы обмануть DBUnit Вещь.
всегда используйте правильные переменные для доступа к специальным каталогам, потому что многомодульные сборки имеют другой рабочий каталог, чем локальные сборки:
так
- вместо
mydir
использовать${project.basedir}/mydir
- вместо
target/mydir
использовать${project.build.directory}/mydir
- вместо
target/classes/mydir
использовать${project.build.outputDirectory}/mydir
эти переменные всегда оцениваются для текущего проекта, независимо от того, откуда он вызывается. Вот это обзор POM переменные (не полный, но самый важный материал там)
кроме того, если вы когда-нибудь захотите выполнить отладку в интерактивном стиле запросов,помощь: оценить mojo пригождается:
просто позвони
mvn help:evaluate
и вам будет предложено выражение. Если ввести выражение, например ${project.build.plugins[0]}
, объединенный dom для указанного элемента будет указан
EDIT:
хорошо, теперь я думаю, что вижу проблема. тогда почему бы просто не ссылаться на каталог в xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "target/test-classes/myapp-data.dtd" >
Я знаю, что это не очень красиво, но он должен работать, многомодульный или нет. текущий каталог для модульных тестов всегда является текущим проектом ${.basedir}, а не Родительский проект dir.
вы можете опубликовать DTD на веб-сервере, а затем поместить его HTTP-URL в DOCTYPE, например:
<!DOCTYPE myapp-data SYSTEM "-//The Owner//The Description//EN" "http://host/path/to/myapp-data.dtd">
попробуйте использовать " файл "вместо" FileInputStream " при открытии XML-файла.
например:
ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new File(fileName)));
таким образом, относительный путь к DTD должен начинаться с каталога XML-файла.
Если вы используете
ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new FileInputStream(fileName)));
путь должен быть относительно текущего рабочего каталога.
Это связано с некоторым уродливым дублированием, но вы можете вставить содержимое DTD в файл(ы) XML, о котором идет речь, а затем использовать их как внутренние DTDs.