I want to make this code testable but the URI
and File
instance created inside the method are giving me problems. I am not able to define mock behavior for them and I don't want to use PowerMock because they don't reflect on Jacoco's test coverage.
If possible can we refactor the code somehow. It would be preferable if we could retain the static nature of the method. As changing that, would mess other parts of the code.
public static List<String> getAbsoluteFilePaths(String dirUrl) throws URISyntaxException {
URI uri = new URI(dirUrl);
File folder = new File(uri);
File[] fileList = folder.listFiles();
List<String> fileNames = new ArrayList<>();
if (fileList != null) {
for (File file : fileList) {
String fileOrDirUrl = uri.getScheme() "://"
(uri.getAuthority() != null ? uri.getAuthority() : "")
file.getAbsolutePath();
if (file.isFile())
fileNames.add(fileOrDirUrl);
else if (file.isDirectory())
fileNames.addAll(getAbsoluteFilePaths(fileOrDirUrl));
}
}
return fileNames;
}
CodePudding user response:
Beside the question if it's useful in this case to mock File
and URI
you could extract the creation of an object via a functional interface.
private static final Function<String, File> fileFactory = File::new;
public static List<String> getAbsoluteFilePaths(String dirUrl) throws URISyntaxException {
File folder = fileFactory.apply(dirUrl);
URI uri = folder.toURI();
File[] fileList = folder.listFiles();
List<String> fileNames = new ArrayList<>();
if (fileList != null) {
for (File file : fileList) {
String fileOrDirUrl = uri.getScheme() "://"
(uri.getAuthority() != null ? uri.getAuthority() : "")
file.getAbsolutePath();
if (file.isFile()) {
fileNames.add(fileOrDirUrl);
} else if (file.isDirectory()) {
fileNames.addAll(getAbsoluteFilePaths(fileOrDirUrl));
}
}
}
return fileNames;
}
CodePudding user response:
According to the specification, the used constructor of class File sets some preconditions that must be met: e.g., the URI has to be absolute, its scheme has to be 'file' and its authority has to be undefined.
Therefore, the construction of the URI can be left to method File#toURI(), so that you can split the method into two testable parts:
class SomeClass {
public static List<String> getAbsoluteFilePaths(String dirUrl) throws URISyntaxException {
URI uri = new URI(dirUrl);
File folder = new File(uri);
return getFileUris(folder);
}
public static List<String> getFileUris(File folder) {
File[] fileList = folder.listFiles();
List<String> fileNames = new ArrayList<>();
if (fileList != null) {
for (File file : fileList) {
if (file.isFile())
fileNames.add(file.toURI().toString());
else if (file.isDirectory())
fileNames.addAll(getFileUris(file));
}
}
return fileNames;
}
}