以下是使用WatchService来使数据与文件同步的简单示例。 我的问题是如何可靠地测试代码。 测试有时会失败,可能是因为操作系统/ JVM将事件放入监视服务中,而测试线程则轮询监视服务之间存在竞争条件。 我希望保持代码简单,单线程和非阻塞,同时也可以进行测试。 我强烈反对在测试代码中加入任意长度的休眠调用。 我希望有更好的解决方案。
public class FileWatcher {
private final WatchService watchService;
private final Path path;
private String data;
public FileWatcher(Path path){
this.path = path;
try {
watchService = FileSystems.getDefault().newWatchService();
path.toAbsolutePath().getParent().register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
load();
}
private void load() {
try (BufferedReader br = Files.newBufferedReader(path, Charset.defaultCharset())){
data = br.readLine();
} catch (IOException ex) {
data = "";
}
}
private void update(){
WatchKey key;
while ((key=watchService.poll()) != null) {
for (WatchEvent<?> e : key.pollEvents()) {
WatchEvent<Path> event = (WatchEvent<Path>) e;
if (path.equals(event.context())){
load();
break;
}
}
key.reset();
}
}
public String getData(){
update();
return data;
}
}
目前的测试情况
public class FileWatcherTest {
public FileWatcherTest() {
}
Path path = Paths.get("myFile.txt");
private void write(String s) throws IOException{
try (BufferedWriter bw = Files.newBufferedWriter(path, Charset.defaultCharset())) {
bw.write(s);
}
}
@Test
public void test() throws IOException{
for (int i=0; i<100; i++){
write("hello");
FileWatcher fw = new FileWatcher(path);
Assert.assertEquals("hello", fw.getData());
write("goodbye");
Assert.assertEquals("goodbye", fw.getData());
}
}
}
PowerMock
(除非完全必要,我会尽量避免使用它) - BretC