Search code examples
javaunit-testingmockingrefactoringstatic-methods

Refactor java static method to make it testable


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;
    }

Solution

  • 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;
        }