### Question:
DirectoryMonitor implements DirectoryScanner { @Override public void scan(final FileChangeListener listener) { List<File> latest = Collections.emptyList(); if (directory.isDirectory()) { latest = new ArrayList<>(asList(directory.listFiles(jsonFiles()))); } Set<File> added = new HashSet<>(); for (File candidate : new ArrayList<>(latest)) { if (!snapshot.containsKey(candidate)) { added.add(candidate); latest.remove(candidate); } } Set<File> removed = new HashSet<>(); for (File candidate : new ArrayList<>(snapshot.keySet())) { if (!latest.contains(candidate)) { removed.add(candidate); snapshot.remove(candidate); } } Set<File> modified = new HashSet<>(); for (File candidate : latest) { long lastModified = snapshot.get(candidate); if (lastModified < candidate.lastModified()) { modified.add(candidate); snapshot.put(candidate, candidate.lastModified()); } } for (File file : added) { snapshot.put(file, file.lastModified()); } if (added.isEmpty() && removed.isEmpty() && modified.isEmpty()) { return; } listener.onChanges(new FileChangeSet(directory, added, modified, removed)); } DirectoryMonitor(final File directory);  DirectoryMonitor(final File directory,
                            final Map<File, Long> snapshot); @Override void scan(final FileChangeListener listener);  }### Answer:
@Test public void testAddedFilesAreDetectedAndStoredInSnapshot() throws Exception { final File directory = getTestResourceDirectory("added"); final HashMap<File, Long> snapshot = new HashMap<>(); DirectoryMonitor observer = new DirectoryMonitor(directory, snapshot); observer.scan(listener); File jsonFile = new File(directory, "new-file.json"); verify(listener).onChanges(argThat(containsAddedFile(jsonFile))); assertThat(snapshot).containsKey(jsonFile); }
@Test public void testNonJsonFilesAreIgnored() throws Exception { final File directory = getTestResourceDirectory("empty"); final HashMap<File, Long> snapshot = new HashMap<>(); DirectoryMonitor observer = new DirectoryMonitor(directory, snapshot); observer.scan(listener); verifyZeroInteractions(listener); assertThat(snapshot).isEmpty(); }
@Test public void testRemovedFilesAreDetectedAndRemovedFromSnapshot() throws Exception { final File directory = getTestResourceDirectory("empty"); final HashMap<File, Long> snapshot = new HashMap<>(); File jsonFile = new File(directory, "new-file.json"); snapshot.put(jsonFile, 0L); DirectoryMonitor observer = new DirectoryMonitor(directory, snapshot); observer.scan(listener); verify(listener).onChanges(argThat(containsRemovedFile(jsonFile))); assertThat(snapshot).isEmpty(); }
@Test public void testModifiedFilesAreDetected() throws Exception { final File directory = getTestResourceDirectory("modified"); final HashMap<File, Long> snapshot = new HashMap<>(); File jsonFile = new File(directory, "new-file.json"); snapshot.put(jsonFile, 0L); DirectoryMonitor observer = new DirectoryMonitor(directory, snapshot); observer.scan(listener); verify(listener).onChanges(argThat(containsModifiedFile(jsonFile))); assertThat(snapshot).contains(entry(jsonFile, jsonFile.lastModified())); }