2

我对多线程系统进行了功能测试。问题是系统使用 System.exit 所以我的 junit 测试没有捕捉到这个错误。因此,如果某个地方 System.exit 被调用,即使在另一个线程中,我也希望我的测试失败。

我使用了 Java:如何测试调用 System.exit() 的方法?以防止 JVM 在 System.exit 上停止并改为抛出 ExitException。我还使用http://blog.cedarsoft.com/2011/12/junit-rule-fail-tests-on-exceptionsfailed-assertions-in-other-threads/来收集这些异常。我希望我的测试在 ExitException 失败后停止。但是这个异常只停止当前线程。我尝试在抛出 ExitException 之前调用 junitThread.interrupt() ,但它仅适用于简单测试。

如果我无法修改线程创建代码,如何在任何线程中抛出 ExitException 时破坏 junit 测试?

4

1 回答 1

1

为什么叫它System.exit()?为什么它会System.exit()在您的单元测试涵盖的级别调用?

如果您想测试退出的代码,您的测试可以生成一个进程并检查它是否已按计划退出。如果您想测试其他功能,请以这样一种方式更好地构建您的应用程序,以使被测代码不会产生如此讨厌的副作用。

但总的来说,我会说有单独的线程调用System.exit()是不良架构的一个强有力的指标。如果任何线程可以立即杀死整个应用程序而不给其他线程清理的机会,那么您可能很快就会遇到一些问题。

如果您的线程调用一些全局关闭处理程序(您可以在测试中覆盖)而不是System.exit()您测试该功能不会有问题。

更新:在处理遗留代码时,我的第一步是将其隔离System.exit()到可以在测试中替换的地方。例如创建一个这样的类:

// "Singleton" with replaceable instance
public class ShutdownHandler {
    private static ShutdownHandler instance = new ShutdownHandler();

    public static ShutdownHandler getInstance() {
        return instance;
    }

    public synchronized void shutdown() {
        // default implementation
        System.exit();
    }

    public static void setInstance(ShutdownHandler newInstance) {
        // (probably also check that this is only called in a test environment)
        instance = newInstance;
    }
}

然后用 替换所有System.exit()调用ShutdownHandler.getInstance().shutdown()。这根本不会改变应用程序的功能。但是现在您可以用ShutdownHandler设置一些标志的实现替换测试中的实例+抛出异常而不是退出 - 然后您的测试可以检查该标志以确定应用程序是否已经退出。

我还可以推荐 Robert C. Martin 的“Working Effectively With Legacy Code”,以获得更多关于如何将旧的混乱变成可管理的东西的想法。

于 2013-05-28T08:51:39.740 回答