我想为我的应用程序编写处理错误方法的Junit测试,它看起来像这样
public void myHandlingError(Throwable t) {//content}
我想模拟Throwable对象,但我找不到任何例子。我是这么想的……
public void myHandlingErrorTest(){
Throwable t = new Exception();
myClass.myHandlingError(t);
.
.
.
任何建议将不胜感激!
术语mock在某种程度上暗示您使用诸如EasyMock这样的模拟框架来创建您正在寻找的对象。但是对于表示异常的对象,很少需要这样做。您可以看到,异常通常是在"错误输入"上创建的。
我的测试通常做的是:将一些"坏"输入驱动到类中;然后预期会抛出某个异常。我的测试捕获该异常,并检索该异常的一个或多个属性;例如它的消息(使用断言验证)。
另一方面,异常是在生产代码中(大多数情况下)使用new创建的。因此,无论如何都没有简单的方法来嘲笑它。为异常创建工厂,使用依赖注入…听起来有点过头了。您可以看到,异常的好处是:在大多数情况下,代码是关于"抛出的错误输入"的。因此,您只是提供了错误的输入,并在测试中抛出异常以进行进一步验证。在你的情况下,你正在测试代码,实际上是接收throwable/exceptions对象作为参数;这里可以使用您开始使用的方法-在测试中创建对象并将其传递给"处理程序"。
为了回应GhostCat的出色回答,您不应该为异常或可抛出对象使用mock。这有几个原因:
- 异常是一种数据对象:异常不是作为协作者,而是在协作者之间携带一段数据。数据对象通常很难模拟,因为有许多
get
方法需要存根(对于可变数据对象更是如此,因为需要模拟set
并附带相应的副作用)。因为数据对象通常没有依赖关系和稳定的实现,所以在测试中使用真实的类几乎没有缺点。 - Throwable有一些难以模拟的系统提供的方法,如
fillInStackTrace
。你不应该从事模拟这样的事情。 - Throwable也有一些无法模拟的
final
方法,如addSuppressed
和getSuppressed
。因为它们是最终的,EasyMock和Mockito不能使用动态代理来覆盖它们,所以即使试图模拟这些方法,你也必须使用PowerMock或其他一些字节码重写模拟工具。 - 有各种现有的,易于实例化,经过良好测试的系统异常,你可以创建和传递,包括
IllegalArgumentException
,NullPointerException
,甚至RuntimeException
本身。 - Throwable, Exception和RuntimeException是非常明确地为子类设计的,所以如果你想用自定义子类进行测试,你可以很容易地在你的测试中创建一个真正的嵌套Exception或Throwable子类。
将模拟留给非数据对象,其中交互对SUT或MUT的一般契约很重要,并为可抛出对象和异常使用真实对象或输入。