模拟框架对我有什么作用?

时间:2011-11-11 15:01:31

标签: java mocking

我听说过一些我无法与之交谈的人是jmock的忠实粉丝。我已经完成了以测试为中心的开发多年,因此我浏览了一些网站,查看了一些文档,但仍然无法弄清楚它有什么用处。

我和春天有同样的问题。如果你已经明白它是什么,那么他们的文档会很好地解释它,所以我不认为jmock是没有价值的。我只是不明白它对我有什么用。

因此,如果jmock为我提供了模拟存根数据的能力,那么让我们举一个如何做事情的例子,看看jmock会更好。

假设我有我的UI层,在创建窗口小部件时创建窗口小部件和窗口小部件服务,初始化窗口小部件并将其中的部分存储在构成窗口小部件所需的三个表中。

当我写测试时,我就是这样做的。

首先,我将hibernate重新指向我的测试高超音速数据库,这样我就不需要做一堆数据库设置了。 Hibernate为我创建了表格。

我的所有测试都有静态工厂方法,可以为我构建类的测试实例。我的每个DAO都创建指向测试模式的测试版本。然后我的服务类有一个用测试类生成的DAO构造自己的服务类。

现在,当我运行调用服务的UI控制器的测试时,我正在测试我的代码一直到应用程序。当然,这不是在进行单元测试时通常需要的完全隔离,但在我看来,它为我提供了更好的单元测试,因为它在所有支持层中执行实际代码。

因为在休眠状态下Hypersonic运行缓慢,所以我需要稍微长一点的时间来运行我的所有测试,但是我的整个版本仍然可以在不到五分钟的时间内在较旧的计算机上运行以进行完整的构建和打包,所以我觉得这很可接受。 / p>

我如何用jmock做不同的事情?

2 个答案:

答案 0 :(得分:6)

在您的示例中,有两个接口,其中一个将使用模拟框架进行适当的单元测试:

  • UI层和窗口小部件服务之间的接口 - 用模拟替换窗口小部件服务将允许您单独测试UI层,服务返回手动创建的数据,模拟验证预期的服务调用(和没有其他事情发生。
  • 小部件服务和DAO之间的接口 - 通过用模拟替换DAO,可以单独测试包含复杂逻辑的任何服务方法。
  

当然,这不是进行单元测试时通常需要的完全隔离,但在我看来,它为我提供了更好的单元测试,因为它在所有支持层中一直执行实际代码。

这似乎是你问题的核心。答案有很多方面:

  • 如果您没有单独测试组件,则没有单元测试,您需要进行集成测试。正如您所观察到的,这些非常有价值,但它们有其缺点
  • 由于他们同时测试更多的东西,他们往往会更频繁地破坏,他们倾向于分成大群(当常见功能出现问题时),当他们这样做时,更难找到实际的位置问题在于
  • 他们在您可以测试的场景中受到更多限制。在集成测试中模拟某些边缘情况可能很困难或不可能。
  • 有时,完整的集成测试无法实现自动化,因为某些组件不在您的控制之下(例如第三方Web服务)来设置您需要的测试数据。在这种情况下,您甚至可能最终在高级集成测试中使用模拟框架。

答案 1 :(得分:1)

我没有特别关注JMock(我使用Mockito)但是通常模拟框架允许你“模拟”外部服务,这样你只需要一次测试一个类。可以模拟该类的任何依赖项,这意味着不进行实际的方法调用,而是调用返回或抛出常量的存根。这是一件好事,因为外部调用可能很慢,不一致或不可靠 - 所有这些都是单元测试的坏事。

举一个如何工作的例子,假设您有一个依赖于Web服务客户端的服务类。如果您使用真实的Web服务客户端进行测试,它可能会关闭,连接可能会很慢,或者Web服务背后的数据可能会随着时间的推移而发生变化。你打算怎么写一个可靠的测试呢? (你不能)。因此,您使用模拟框架来模拟/存根Web服务客户端,并创建虚假响应,假错误,虚假异常,以模仿Web服务行为。不同之处在于结果始终快速且一致。

此外,您还要测试给定依赖项可能具有的所有失败案例,但不要嘲笑这很难做到。考虑我上面给出的例子。如果Web服务因为Web服务停机(或超时)而抛出IOException,您希望确保您的代码做正确的事情,但强制执行该条件并不容易。通过嘲弄,这变得微不足道。