java - 如何在 Junit 中测试 ScheduledExecutorService 异常处理?

标签 java multithreading junit scheduledexecutorservice

我有一个任务,计划每 30 分钟运行一次。我使用ScheduledExecutorService来调度。

我想测试(junit)ScheduledExecutorService 的异常处理,这样当抛出异常时,线程不会因为异常而死亡。

我的代码:

public enum MonitorTask {
    TIMER;
    private final AtomicBoolean isPublishing = new AtomicBoolean(false);
    private final long          period       = 18000000

    public synchronized boolean initialize() {
        return initialize(period, period);
    }

    /**
     * @return true, if call was successful i.e. Timer task was scheduled
     */
    boolean initialize(long delay, long period) {
        if (isPublishing.get()) {
            log.warn("Already monitoring for new feature data");
            return false;
        }

        //execute on daemon thread
        ScheduledExecutorService scheduledExecutorService =
                Executors.newSingleThreadScheduledExecutor(runnable -> {
                    Thread thread = new Thread(runnable);
                       thread.setDaemon(true);
                       return thread;
                  }
                );

        Runnable runnableTask = () -> {
            try {
                DataPublisher.INSTANCE.update(DateTime.now());
            } catch (Throwable e) {
                log.warn("Failed to check for new Data!", e);
            }
        };    

        scheduledExecutorService.scheduleAtFixedRate(runnableTask, delay, period, TimeUnit.MILLISECONDS);
        isPublishing.set(true);
        return true;
    }
}

目前,我的单元测试检查功能:

public class MonitorTaskTest {    
    @Test
    public void testInitialize() throws Exception {
        AtomicInteger val = new AtomicInteger(0);
        DataProvider provider = testProvider(val);
        assertEquals(0, val.get());
        // this should update val  every 10 ms ( adds 1 to val )
        Assert.assertTrue(MonitorTask.TIMER.initialize(0, 10));
        assertEquals(0, val.get());
        DataPublisher.INSTANCE.registerForNewData(provider, DateTime.now());
        // wait for 3 updates
        Thread.sleep(10 * 3);
        Assert.assertTrue("Expected val to be >= 3 but is " + val.get(), val.get() >= 3);
    }

    @Before
    public void setUp() {
        DataPublisher.INSTANCE.clear();
    }

    private static DataProvider testProvider(final AtomicInteger ai) {
        return new DataProvider() {
            private AtomicInteger val = ai;

            @Override public boolean update(DateTime dateTime) throws Exception {
                val.incrementAndGet();
                return true;
            }

            @Override public boolean exists(DateTime dateTime) {
                return true;
            }

            @Override public void close() throws Exception {

            }
        };
    }
}

最佳答案

我认为你走错了地方。含义:当您检查javadoc时对于您正在使用的方法,您会发现:

Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.)

换句话说:您问的是如何测试您正在使用的 Java 系统库保证工作的东西。从这个意义上说,你是在浪费时间。

可能宁愿花时间改进代码以使其更易于测试。你看,当你的类接收一个 ExecutorService 对象(而不是为自己创建一个)时,你可以传入 same thread executor 。用于您的单元测试。突然之间,您的单元测试可以在一个线程上运行,这使得整个测试变得更加容易 - 因为它允许您摆脱sleep语句测试。 (尽管系统库保证您会重新启动线程,但这些 sleep 语句的问题比线程未重新启动的可能性更大)。

除此之外:您的可运行程序已经以某种方式编写,该方式应该保证运行此代码的线程永远不会死亡(当然,这是有问题的 em> 捕获 Throwable)。但为了测试这一点,我想您需要另一个“测试提供程序”,其中 update() 抛出任何类型的异常。

关于java - 如何在 Junit 中测试 ScheduledExecutorService 异常处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45427243/

相关文章:

java - AssertionFailedError : Maven 3. 需要 2.4 或更高版本(运行版本 3.2.5)

spring - 如何使用 Spring 的 RestTemplate 模拟 curl REST 调用?

Java Web 服务客户端无法从 cdyne.com 访问天气服务

java - 查找 Eclipse 构建的类文件

java - JButton 布局设置

Java 在 SwingWorker 中渲染游戏 map 无法正常工作

java - Wildfly 8.0 服务器中的 JMS 消息持久化

multithreading - 原子比较交换。这是对的吗?

c# - 控制任务的实际并发性

spring - 使用 spring-test-mvc 在 Spring Controller 测试中未注入(inject)服务