如何使这个 SwingWorker 代码可测试

2024-03-07

考虑这段代码:

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 和桌面具有单例的所有“优点”,并且异常处理使得不可能轻松地包装 get。

那么测试这段代码的好解决方案是什么?


恕我直言,这对于匿名类来说很复杂。我的方法是将匿名类重构为如下所示:

public class FileWriterWorker extends SwingWorker<File, Void> {
    private final String location;
    private final Response target;
    private final Object creator;

    public FileWriterWorker(Object creator, String location, Response target) {
        this.creator = creator;
        this.location = location;
        this.target = target;
    }

    @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() {
        try {
            File file = get();
            target.success(file);
        }
        catch (InterruptedException ex) {
            target.failure(new BackgroundException(ex));
        }
        catch (ExecutionException ex) {
            target.failure(new BackgroundException(ex));
        }
    }

    public interface Response {
        void success(File f);
        void failure(BackgroundException ex);
    }

    public class BackgroundException extends Exception {
        public BackgroundException(Throwable cause) {
            super(cause);
        }
    }
}

这允许独立于 GUI 来测试文件写入功能

然后,actionPerformed变成这样:

public void actionPerformed(ActionEvent e) {
    setEnabled(false);
    Object creator;
    new FileWriterWorker(creator, url.getText(), new FileWriterWorker.Response() {
        @Override
        public void failure(FileWriterWorker.BackgroundException ex) {
            setEnabled(true);
            Throwable bgCause = ex.getCause();
            if (bgCause instanceof InterruptedException) {
                logger.log(Level.INFO, "Thread interupted, process aborting.", bgCause);
                Thread.currentThread().interrupt();
            }
            else if (cause instanceof ExecutionException) {
                Throwable cause = bgCause.getCause() == null ? bgCause : bgCause.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);
            }
        }

        @Override
        public void success(File f) {
            setEnabled(true);
            JOptionPane.showMessageDialog(FileInputFrame.this,
                "File has been retrieved and saved to:\n"
                + file.getAbsolutePath());
            try {
                Desktop.getDesktop().open(file);
            }
            catch (IOException iOException) {
                logger.log(Level.INFO, "Unable to open file for viewing.", ex);
            }
        }
    }).execute();
}

另外,实例FileWriterWorker.Response可以分配给一个变量并独立于进行测试FileWriterWorker.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使这个 SwingWorker 代码可测试 的相关文章

随机推荐

  • 多个元素的布尔运算符

    我知道有人可以做 any gt 3 1 2 3 4 5 但优雅的实现方式是什么 any and gt 3 lt 5 1 2 3 4 5 or all or lt 2 gt 4 1 2 3 4 5 etc 我相信您想检查是否有任何元素同时存在
  • Android Tabhost更改文本颜色样式

    尝试更改 tabhost 文本颜色 在这段代码中我可以更改 tabhost 背景颜色 不是文本颜色 tabHost setOnTabChangedListener new OnTabChangeListener Override publi
  • C++ - 在 Visual Studio 2010 的属性表中使用环境变量

    我想建立一个使用 OpenCV 的项目 所以基本上 我必须使用 Visual Studio 2010 中的属性管理器添加一个新的属性表 基本上 我必须将路径添加到我的include and lib文件夹以使 OpenCV 正常运行 我想将我
  • 如何删除 HTML 节点之间的空白?

    我正在尝试从 HTML 片段中删除空格 p tags p p Foo Bar p p bar bar bar p p bla p 正如你所看到的 之间总是有一个空格 p p tags 问题是空白会产生 br 将字符串保存到我的数据库时的标签
  • Spark SQL“限制”

    环境 使用 Hadoop 的 Spark 1 6 Hortonworks 数据平台 2 5 我有一个包含 100 亿条记录的表 我想获取 3 亿条记录并将它们移到临时表中 sqlContext sql select from my tabl
  • 如何聚焦位于子组件中的输入字段

    我在父组件中有一个按钮 我想通过单击该按钮来聚焦位于子组件中的输入字段 我该怎么做 您可以利用refs达到结果 class Parent extends React Component handleClick gt this refs ch
  • Laravel 身份验证,我无法检索登录的用户

    Auth check 总是返回 false 这很奇怪 因为登录函数将我重定向到 redirectTo url 因此尝试成功 但之后我无法检索用户 我正在使用 Laravel 5 2 14 和 Xampp 我不知道还要写什么 因为它应该是开箱
  • Swing 桌面开发

    我有一个关于 java 桌面 GUI 应用程序的非常普遍的问题 我的经验 在过去的几年里 我开发了许多桌面应用程序 其中一些单独使用 Swing 一些使用 Spring RCP 这很棒 但我仍然不能只押注于一个已经超过 3 年没有更新的框架
  • 设备重新启动后,AVSampleDisplayBuffer 随机挂起

    问题描述 AVSampleBufferDisplayLayer 似乎在 iOS 12 3 1 上挂起 gt iOS 12 2 也受到影响 重启 看起来 5 分钟后一切又恢复正常了 该问题在 iOS 11 上无法重现 在我们的生产代码中 我们
  • 在 /usr/share/phpMyAdmin/libraries/Error.class.php 中找不到 phpMyAdmin 类“PMA_Message”

    我刚刚收到此错误 过去 2 年 phpMyAdmin 中没有错误 PHP 致命错误 在第 24 行 usr share phpMyAdmin libraries Error class php 中找不到类 PMA Message 我尝试搜索
  • 如何强制 ghc 的分析器更深入地了解库?

    我正在尝试分析我的程序 所以我编译它 prof and auto all标志并运行 P获取详细的分析报告 ghc make prof auto all Test hs Test RTS P 这是一份分析报告 COST CENTRE MODU
  • R 将 KS 测试逐行应用于 2 个矩阵

    我在 R 中有两个矩阵 A 和 B 行数相同 但列数不同 我想运行一个柯尔莫哥洛夫 斯米尔诺夫检验 https stat ethz ch R manual R devel library stats html ks test html每个矩
  • 在 PowerShell 中拆分不带分隔符的字符串

    我想分割一个字符串并将结果标记存储在变量中 例如我的字符串是160519 我想以一种方式分割它16 05 and 19存储在单独的变量中 我尝试使用 split 但是因为我的字符串没有分隔符 所以我发现很难剪切字符串 如果使用正则表达式 实
  • 从另一个表单添加到列表视图

    我想知道如何通过在 form2 中的文本框输入数据来更新 form1 中的列表视图 如果我将所有文本框放在同一个表单上 我的代码可以正常工作 我想我需要对第二个表格的一些参考 但无法让它工作 任何能让我朝着正确方向前进的建议都会很好 也有任
  • RegisterStartupScript 似乎无法在更新面板内进行页面回发

    好的 所以我正在开发一个使用自定义日期选择器控件的系统 我知道还有其他控件 但为了保持一致性 我想了解为什么我当前的问题发生并修复它 所以它是一个带有文本框的自定义用户控件 在 Page PreRender 上执行以下操作 protecte
  • 在asp.net core rc2应用程序的ActionFilterAttribute中访问IConfiguration [重复]

    这个问题在这里已经有答案了 我正在编写将验证验证码的属性 为了正常工作 它需要知道秘密 我将其保留在设置中 秘密管理器工具 但是我不知道如何从属性类读取配置 asp net core中的DI支持构造函数注入 不支持属性注入 所以这会报编译错
  • 将图像从浏览器保存到手机图库

    因此 纯粹从安全角度来看 这似乎不太可能 但我需要做好基础工作 有没有人遇到过将浏览器中的图像保存到用户图库的方法 在本例中 我专门谈论来自站点服务的 javascript 不是音位间隙 虽然我知道您可以点击并按住图像进行保存 但我希望为技
  • 帮助小商店在“乔尔测试”中获得更高分数的工具

    关于问题 1 至问题 4乔尔测试 http www joelonsoftware com articles fog0000000043 html我认为都是关于正在使用的开发工具和为开发人员提供的支持系统 您使用源代码管理吗 你能一步完成构建
  • 如果您按住 Ctrl 键单击或按住 Rt 键单击通知图标,如何获得不同的上下文菜单?

    我有一个基于系统托盘的应用程序 如果您右键单击它 我有一个很好的上下文菜单 但是如果您左键单击它 我希望显示一个不同的上下文菜单 现在我让不同的菜单显示出来 private void niTrayIcon MouseClick object
  • 如何使这个 SwingWorker 代码可测试

    考虑这段代码 public void actionPerformed ActionEvent e setEnabled false new SwingWorker