【发布时间】:2011-03-06 03:25:40
【问题描述】:
考虑这段代码:
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 变得不可能。
那么什么是测试这段代码的好方法呢?
【问题讨论】:
-
重新格式化的代码;如果不正确,请恢复。
-
不是一个完整的答案:但如果你喜欢高质量的代码,请不要靠近
SwingWorker。一般来说,把事情排除在外。如果您有一个使用静态/单例的 API,则会引入一个接口,该接口使用“真实”静态 API 的实现和另一个用于模拟(可能另一个用于审计)。 -
@Tom,如果您有时间编写 SwingWorker 的替代设计大纲(或者如果您知道替代更好的实现),我们将不胜感激。
标签: java unit-testing swing tdd swingworker