【问题标题】:What's the 'correct' way to test Runnables that can not be directly seen by a JUnit test?测试 JUnit 测试无法直接看到的 Runnables 的“正确”方法是什么?
【发布时间】:2015-06-11 10:37:24
【问题描述】:

我要创建一系列测试,其中一些测试导致部分工作在单独的线程中完成。因为这项工作发生在另一个线程中,并且它不接受任何对象作为参数,所以 JUnit/Mockito 无法看到线程内部发生的事情。这意味着如果代码以某种方式失败,那么 JUnit 就看不到抛出的异常,这意味着它会假设在测试期间没有抛出异常,并且可能在不应该的时候“通过”它。

有问题的可运行对象不直接与启动它的线程通信,所以目前我一直在创建测试,这些测试只是寻找线程对其工作的其他文件的外部印象,调用数据库,等等

这是一种可靠的测试方法吗?这听起来有没有我没有考虑过的问题?我应该模拟创建这个可运行文件的部分,然后自行测试可运行文件吗?还是我应该采取其他更好的路径?


注意:很遗憾,我无法对正在测试的代码进行任何修改。

【问题讨论】:

  • 我知道这没什么用,但是如果您不能修改代码,那么测试代码又有什么意义呢?如果在代码中发现错误怎么办?我通常会将业务逻辑移出可运行对象并从可运行对象中调用它。这意味着您可以单独测试业务逻辑。
  • 我正在编写的代码可以正常工作,它已经过手动测试,因此目前无法正常工作的可能性很小。将来,当新项目开始工作时,将对代码进行更改。为了在这些新项目期间节省时间,现在正在创建自动化单元测试。
  • 这取决于您的 Runnable 是如何创建和运行的,但如果您只想测试正确性(而不是测试并发性),您可以使用某种 Executor,您可以传入“mocked " 强制所有内容同步的仅测试构造函数的执行器。

标签: java multithreading unit-testing junit


【解决方案1】:

看看ConcurrentUnit。它允许将任何线程中的断言和失败正确地报告回主测试线程,以便您的测试按预期通过或失败。

如果您无法控制可能失败的 Runnable,您可以使用 Thread.setDefaultUncaughtExceptionHandler 来处理任何意外失败,方法是让它们调用 waiter.fail(throwable)

final Waiter waiter = new Waiter();

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(){
  @Override
  public void uncaughtException(Thread arg0, Throwable throwable) {
    waiter.fail(throwable);
  }
});

【讨论】:

    【解决方案2】:

    如果不确切知道可运行对象中发生了什么以及是否可以重构它们,很难提供更多帮助。

    也许您可以将侦听器传递给 runnable 以使其更具可测试性。

    public interface Listener {
       void onSuccess(Object context);
       void onError(Object context, Throwable t);
    }
    
    public class MyRunnable implements Runnable {
        private Listener listener;
        /// constructor;
        public void run() {
           Object context = ...;
           try {
              doStuff(context);
              listener.onSuccess(context);
           } catch (Throwable t) {
              listener.onError(context, t);
           }
        }
    }
    

    如果您无法重构可运行文件,那么您唯一可以测试的就是外部效果。如果这是一个单元测试并且您已经实现了 IOC,您可以模拟服务依赖项并测试服务调用(例如使用 Mockito)。

    【讨论】:

    • 恐怕我无法重构它们,我现在会更新我的问题。所以你会建议只测试外部可观察的效果是最好的方法,而不是打扰它的创建,然后在 JUnit/Mockito 可以看到的地方自行测试可运行文件?
    猜你喜欢
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    相关资源
    最近更新 更多