RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 593043
Accepted
A1essandro
A1essandro
Asked:2020-11-19 19:12:25 +0000 UTC2020-11-19 19:12:25 +0000 UTC 2020-11-19 19:12:25 +0000 UTC

JUnit 和中断异常

  • 772

我正在学习 Java(到目前为止是为了自我开发,然后是如何进行)。该类有一个方法可以开始生成一个可能很大的数组。并且有一种获取此数组的方法。分离的,用于在单独的线程中实现生成的方法。

public float[][] getTerra() {
    if (task.isAlive()) {
        try {
            task.join(); //жду, чтобы terra сгенерилась до конца
        } catch (InterruptedException ignored) { // <--- Codecov redline
            //empty
        }
    }
    return terra;
}

codecov(单元测试覆盖率)显示处理未以任何方式进行测试catch (InterruptedException)。task如果字符串是一个私有对象,并且不希望有外部访问,你怎么能用测试覆盖它呢?还是我错误地等待线程结束?

java
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    etki
    2020-11-19T20:42:22Z2020-11-19T20:42:22Z

    你真的应该重写数组生成算法本身,这既是因为返回值的不确定性,也是因为你无法测试它,特别是,你可以通过将它从一个单独的线程变成一个单独的线程来显着改进数组生成任务。

    在这种特殊情况下,您的手脚被束缚有两个原因:

    • 您自己在代码中生成一个新线程
    • 线程模型假定它们的执行顺序是任意的

    因此,只要您在调用上述方法之前不更改线程引用本身,或者您不将无限任务推送到该线程中,Java 正式有权在您尝试调用InterruptedException等待之前完成线程计算线。

    展望未来,这与所谓的密切相关。函数纯度:纯函数为每组输入参数返回确定性结果,并且没有外部影响(副作用,函数外部世界的任何状态变化)。您提供的方法与您无法直接控制的这些相同的副作用密切相关,严格来说,只能对或多或少的纯功能进行正式测试(因为否则无法验证并且维护成本高-如果代码绑定到外部状态,那么测试必须不可避免地在测试之前重新创建它)。

    具体来说,在这种情况下,您无法以任何方式控制外部状态(在正确的时间执行或不执行线程),因为您的代码涉及直接调用以更改外部状态(启动线程);同时,在不参考外部状态的情况下,您无法测试您的代码。但是,如果您将任务的执行委托给其他人,那么您可以轻松地在测试中重新创建此状态。为了解决所有问题,我建议使用接口功能ExecutorService- 这是一项允许您注册任务以供其执行的服务,而接口本身并不能保证任务将在何处以及如何执行 - 它可以是相同的流、另一个流、另一台机器,或者它会打印出来在纸上并发送给数学家来解决。在这种情况下,您的代码可能如下所示:

    public class MapContainer {
    
        private final ExecutorService executor;
        private volatile Future generationTask;
        private volatile float[][] map;
    
        public MapContainer(ExecutorService executor) {
            this.executor = executor;
        }
    
        public synchronized void generate() {
            if (map != null) {
                return;
            }
            generationTask = executor.submit(() -> { map = compute(); });
        }
    
        public float[][] get() {
            generate();
            try {
                generationTask.get();
            } catch (Exception e) { 
            }
            return map;
        }
    }
    

    我会提前警告您,代码非常脏且不正确 - 除了任务委派的即时时刻。这里你发送一个任务给ExecutorService,它会找出去哪里执行任务,然后等待它完成。现在您可以在程序代码中使用其中一种方法的结果Executors.*,并在测试中使用您自己的实现,这将返回Future以下字符:

    public void get() throws InterruptedException {
        while (true) {
            Thread.sleep(1000);
        }
    }
    

    因此,该方法的执行时间仅通过调用.interrupt()正在执行的线程并抛出相应的异常来限制,这是测试所需要的。现在您可以创建一个线程,调用它mapContainer.get()并中断线程本身,以强制代码沿着指定的分支传递。

    没关系?

    实际上,不是真的,因为代码仍然充满了对外部状态的调用,而建议的带有 Future 的版本,如果处理不当,真的会永远运行下去,这可能会挂掉你的 CI 服务器。但如果不在这里重建整个东西,我恐怕无法提供更好的选择。将 InterruptedException 视为阻止程序正常运行的东西会容易得多(只要你不.interrupt为自己的目的调用,它确实是)——在这种情况下,你可以而且应该抛出异常,在更高级别捕获它并终止程序。

    在任何情况下,您都应该努力保持代码整洁,因为除其他外,它有助于防止这种情况并将异常处理推到程序的外围(而不是将这种处理分散到所有组件)

    作为后记:它甚至比上述所有内容都更好,可以应对任务CompletableFuture,但我决定不使已经歪曲的文本复杂化。

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5