Вот в чем дело: обычно для правильной работы модульного тестирования необходимо предоставить своим классам интерфейсы , а не конкретные классы, чтобы вы могли гибко выполнять разные задачи для тестирования.Глядя на ваш пример, мне кажется, что вы должны взять на себя ответственность за загрузку Document
в какой-то другой класс ... с помощью интерфейса с именем DocumentSource
, скажем.
Тогда ваш код здесь не будетне зависит от файловой системы вообще.Это может выглядеть примерно так:
public SomethingProductDataProvider(DocumentSource source, String tocDocumentName,
boolean checkTocModifications) {
this.source = source;
this.tocDocumentName = tocDocumentName;
this.checkTocModifications = checkTocModifications;
this.toc = loadToc();
}
private ReadonlyTableOfContents loadToc() {
Document doc = source.getDocument(tocDocumentName);
if (doc == null) {
throw new IllegalArgumentException("Can' find table of contents file " +
tocResourcePath);
}
try {
Element tocElement = doc.getDocumentElement();
ReadonlyTableOfContents toc = new ReadonlyTableOfContents();
toc.initFromXml(tocElement);
return toc;
} catch (Exception e) {
throw new RuntimeException("Error creating toc from xml.", e);
}
}
В качестве альтернативы, вы можете получить класс, взяв Document
или даже InputStream
непосредственно в своем конструкторе.Конечно, в какой-то момент вам нужен реальный код, который загружает InputStream
из ресурса, используя ClassLoader
... но вы можете вставить этот код во что-то простое, что только делает это.Тогда становится ясно, что при любом тестировании того, что класс должен использовать реальный файл ... но на тестирование других классов это не влияет.
Как примечание, это плохой признакдля тестируемости класса, если он работает (например, загрузка оглавления в данном случае) в его конструкторе.Вероятно, существует гораздо лучший способ разработки классов, задействованных здесь, который устраняет необходимость в этом и является более тестируемым, но трудно точно сказать, что именно этот дизайн дает именно этому.
Существуют различные другие вариантычто вы могли бы сделать, в том числе использовать что-то вроде интерфейса InputSupplier в Guava в сочетании с уже проверенным заводским методом, таким как Resources.newInputStreamSupplier (URL) для получения экземпляра InputSupplier
для использования в производстве.Главное, чтобы ваши классы всегда зависели от интерфейсов, чтобы вы могли легко использовать альтернативные реализации в тестировании.