这篇文章的开头是“单元测试多线程代码中有哪些常见模式?”,但我在SO上发现了一些other discussions,它们普遍认为“它很难(TM) )“和”它取决于(TM)“。所以我认为减少问题的范围会更有用。
背景 :我们正在实施一个简单的调度程序,它为您提供了一种在启动和停止作业时注册回调的方法,当然还可以配置调度的频率。目前,我们正在围绕java.util.Timer创建一个轻量级的包装器。
方面 :
我还没有找到一种方法来依赖公共接口(类似addJob(jobSchedule, jobArgs,jobListener)
,removeJob(jobId)
)来测试这个调度程序。
如何根据指定的时间表计算作业被调用的事实?
答案 0 :(得分:6)
您可以使用记录器对象记录调度程序的每个单元测试中的顺序,时间和其他有用的内容。测试很简单:
答案 1 :(得分:4)
还有一件事要记住,你不需要测试Timer的工作原理。您可以编写一个模拟版本的Timer(通过扩展类或使用EasyMock),它只是检查您是否正确调用它,甚至可能替换为您根本不需要线程。在这种情况下,如果您的作业监听器有足够的回调来跟踪调度程序,则可能需要的工作量超出需要。
要记住的另一个重要事项是,在测试调度程序时,使用跟踪调度程序工作方式的自定义作业;在测试预定作业时,直接调用回调而不是通过调度程序。根据系统的不同,您可能需要进行更高级别的集成测试,以便同时进行检查。
答案 2 :(得分:3)
此类调度程序可能会出现许多故障模式,并且每种模式都很可能需要自己的测试用例。这些测试用例可能非常不同,所以“这取决于。”
为了测试Java中的并发软件,我推荐JavaOne 2007中的这个演示文稿:Testing Concurrent Software。
为了测试调度程序必须准确地按照其计划执行作业,我将创建一个时间抽象本身。我在我的一个项目中做了类似的事情,我有一个时间或时钟界面。默认实现将是MillisecondTime,但在测试期间,我将使用TickTime将其切换出来。这个实现将允许我的单元测试控制时间的进展和多少。
通过这种方式,您可以编写一个测试,其中作业计划每10个刻度运行一次。然后你的测试只是提前打勾计数器并检查以确保作业以正确的刻度运行。
答案 3 :(得分:1)
测试并发代码的几种方法。
如果您发现难以测试并发性,请考虑重构对象/组件以使其更易于测试。
答案 4 :(得分:1)
如果调度程序委托给Executor
或ExecutorService
运行任务,则可以使用“依赖注入”来删除对Executor
和{{3}类型的直接依赖}来测试调度程序 的许多功能,而无需复杂的真正多线程代码。一旦调试好了这些测试,就可以继续进行难度更高但现在大大减少的线程安全测试任务。