0

我已经花了最近几个小时试图找出测试这段代码的最佳方法。如何使用Stream.generate进行单元测试方法?

void consume() { 
    executorService.execute(() -> Stream.generate(this::takeFromQueue) 
     .filter(Optional::isPresent) 
     .map(Optional::get) 
     .forEach(messageSender::send)); 
} 

private Optional<Message> takeFromQueue() { 
    try { 
    return Optional.ofNullable(queue.take()); 
    } catch (InterruptedException e) { 
    log.error("Queue consumer interrupted."); 
    return Optional.empty(); 
    } 

}

代码的想法是提供一种的BlockingQueue的消费者,在一个单独的线程,直到应用程序结束运行。 在这种情况下,我不能模拟executorService,因为测试会挂起等待线程完成无限流。如果我将执行运行放在单独的线程中,测试将不会确定,我需要依赖Thread.sleep来给它时间以至少消耗队列中的消息。 任何想法?

感谢。

+1

没有理由来测试'Stream.generate',该方法已经很好的测试。你应该为'takeFromQueue()'和'send()'做测试用例,而不是普通的流链。顺便说一下,'take()'永远不会返回'null',因此,没有理由使用'ofNullable'。既然你有效循环并忽略中断,只需再次调用'take()',那么根本就不需要处理'Optional'。在'takeFromQueue'内循环直到'take()'成功将产生相同的效果。 – Holger

+0

对不起,我猜标题是不正确的。我不想测试Stream.generate,我想测试使用它的代码。我没有得到应该测试'takeFromQueue()'的部分,对我来说这不是那么重要,特别是如果我删除'Optional'并且它只能永远循环。我认为我应该测试的是从队列中取出的每个对象都被发送到'messageSender'。这就是我不知道该怎么做的基本原因,因为在单个线程场景中,测试会在队列中挂起,而在多线程场景中则取决于系统的速度。 – Kilian

+0

测试“从队列中取出的每个对象都发送给'messageSender'”意味着测试'consume()'方法是否完成其工作。所以它根本不涉及Stream API。但是测试一个包含无限循环的方法有其障碍...... – Holger

回答

0

我建议改变方法消耗()消耗(流) 并在测试中用一个固定大小的流调用它。

在比消耗称它为你真正的代码(Stream.generate(这:: takeFromQueue))

相关问题