consideran este código:¿Cómo puede el código SwingWorker hacerse comprobable
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
es un JTextField y 'creador' es una interfaz inyectado para escribir el archivo (de modo que parte se encuentra bajo prueba). La ubicación en la que se escribe el archivo está codificada a propósito porque pretende ser un ejemplo. Y java.util.logging se usa simplemente para evitar una dependencia externa.
¿Cómo clasificaría esto para que sea comprobable por unidad (incluido el abandono de SwingWorker si fuera necesario, pero luego reemplazando su funcionalidad, al menos como se usa aquí).
Por la forma en que lo miro, el doInBackground está básicamente bien. La mecánica fundamental es crear un escritor y cerrarlo, que es casi demasiado simple de probar y el verdadero trabajo está bajo prueba. Sin embargo, el método done es problemático, incluido su acoplamiento con el método actionPerformed, la clase principal y la coordinación de la activación y desactivación del botón.
Sin embargo, separar eso no es obvio. Inyectar algún tipo de SwingWorkerFactory hace que la captura de los campos de la GUI sea mucho más difícil de mantener (es difícil ver cómo sería una mejora en el diseño). El JOpitonPane y el Escritorio tienen toda la "bondad" de Singletons, y el manejo de excepciones hace que sea imposible ajustar el get fácilmente.
Entonces, ¿cuál sería una buena solución para poner este código a prueba?
Código reformado; por favor revertir si es incorrecto. – trashgod
No es una respuesta completa: pero si te gusta el código de calidad, no te acerques a 'SwingWorker'. En general factorizar las cosas. Donde tenga una API que use statics/singletons, introduzca una interfaz con una implementación que use la API estática "real" y otra para la burla (posiblemente otra para la auditoría). –
@Tom, si tiene tiempo para escribir el esquema de un diseño alternativo a SwingWorker (o si conoce una mejor implementación alternativa) sería muy apreciado. – Yishai