考虑这段代码:
public void actionPerformed(ActionEvent e) {
setEnabled(false);
new SwingWorker<File, Void>() {
private String location = url.getText();
@Override
protected File doInBackground() throws Exception {
File file = new File("out.txt");
Writer writer = null;
try {
writer = new FileWriter(file);
creator.write(location, writer);
} finally {
if (writer != null) {
writer.close();
}
}
return file;
}
@Override
protected void done() {
setEnabled(true);
try {
File file = get();
JOptionPane.showMessageDialog(FileInputFrame.this,
"File has been retrieved and saved to:\n"
+ file.getAbsolutePath());
Desktop.getDesktop().open(file);
} catch (InterruptedException ex) {
logger.log(Level.INFO, "Thread interupted, process aborting.", ex);
Thread.currentThread().interrupt();
} catch (ExecutionException ex) {
Throwable cause = ex.getCause() == null ? ex : ex.getCause();
logger.log(Level.SEVERE, "An exception occurred that was "
+ "not supposed to happen.", cause);
JOptionPane.showMessageDialog(FileInputFrame.this, "Error: "
+ cause.getClass().getSimpleName() + " "
+ cause.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
} catch (IOException ex) {
logger.log(Level.INFO, "Unable to open file for viewing.", ex);
}
}
}.execute();
url
是一个 JTextField,'creator' 是一个用于写入文件的注入接口(因此该部分正在测试中)。写入文件的位置是故意硬编码的,因为这只是一个示例。并且 java.util.logging 仅用于避免外部依赖。
您将如何将其分块以使其可单元测试(包括在需要时放弃 SwingWorker,但随后替换其功能,至少如此处使用的那样)。
在我看来,doInBackground 基本上没问题。基本机制是创建一个作家并关闭它,这几乎太简单而无法测试,而真正的工作正在测试中。但是, done 方法存在引用问题,包括它与父类的 actionPerformed 方法耦合以及协调按钮的启用和禁用。
但是,将其分开并不明显。注入某种 SwingWorkerFactory 使得捕获 GUI 字段变得更加难以维护(很难看出这将如何改进设计)。JOpitonPane 和 Desktop 具有 Singleton 的所有“优点”,并且异常处理使得无法轻松包装 get。
那么什么是测试这段代码的好解决方案呢?