测试开发

《JUnit实战》第6章 使用stub进行粗粒度测试(续3)

6.4 替换连接

到目前为止,你已经替换了Web服务器的资源了。接下来,我们要替换HTTP 连接。这样做的话会妨碍你有效地测试连接,但是这没关系,因为它并不是你此时真正的目的。你真正想要做的是测试解决方案中的代码。在后面的阶段中,可以使用功能测试或集成测试来测试连接。

当不需要改变代码就可以替换连接的时候,我们就会发现,得益于Java的URL和HttpURLConnection类,我们可以引人自定义的协议处理器来处理任何类型的通信协议。你可以使任何对HttpURLConnection类的调用指向你自己的测试类,这些类会返回测试中需要的任何内容。

6.4.1 创建自定义的 URL 协议处理器

为了实现一个自定义的URL 协议处理器,你需要调用URL的setURLStreamHandlerFactory方法,并传给它一个自定义的URLStreamHandlerFactory。无论何时调用URL的openConnection方法,都会调用URLStreamHandlerFactory 类返回一个URLStreamHandler对象。代码6.6给出了实现这个过程的代码。其想法是在JUnit的setUp方法中调用URL的静态方法 setURLStreamHandlerFactory。(更好的实现会使用到TestSetup类,以至于它在整个测试集执行期间只运行一次。)

image.png

image.png

为了能够使用StubHttpURLConnection类,我们使用了几个(内部)类(②和③)。我们从调用setURLStreamHandlerFactory1和第一个 stub类 StubstreamHandlerFactory开始。在StubstreamHandlerFactory 中,我们覆写createURLStreamHandler方法②,在这个方法中我们返回了第2个私有的stub类StubHttpURLStreamHandler的一个新实例。在StubHttpURLStream Handler中,我们覆写了一个方法 openConnection来根据给定的URL打开一个连接③。

为了简单起见,你也能够使用匿名的内部类,但是这个方法将会使得代码更加难以阅读。注意,你目前还没有编写StubHttpURLConnection类,我们会在下一节中详细介绍这个类。

6.4.2 创建一个JDK的HttpURLConnection stub

最后一步将是创建一个HttpURLConnection类的stub实现,以便你可以返回测试中想要的任何值。代码6.7给出一个简单的实现,它返回字符串“It works”作为一个流传给调用者。

image.png

image.png

HttpURLConnection是一个抽象的公有类,它并没有实现一个接口,所以你可以继承它并覆写需要替换的方法。在这个stub 中,你提供了getInputstream方法的实现,因为它是待测代码所使用的唯一方法。如果待测代码较多地使用了HttpURLConnection 的API,那么你就需要替换这些额外的方法。这就是代码变得越来越复杂的原因所在——你需要完全复制与真正的HttpURLConnection相同的行为。例如,在①处,你测试了待测代码中的setDoInput(false)是否已经被调用了,然后调用getInputstream方法返回一个 ProtocolException异常(这就是HttpURLconnection的行为)。幸运的是,在多数情况下,你只需要替换些方法,而不是整个APl。

6.4.3 运行测试

我们来运行TestWebclient1测试,它使用了StubHttpURLConnection。图6.5显示在Eclipse中执行该测试的结果。

正如你所看到的,替换连接要比替换 Web资源更加容易。这个方法与上文提到的方法相比,并没有执行相同程度的测试(你没有进行继承测试),但是它能使你更加容易地为Webclient逻辑编写专门的单元测试。

image.png

图6.5 执行TestWebClient1的结果(其使用了 StubHttpURLConnection )

6.5 小结

在本章中,我们介绍了如何使用stub帮助我们对访问远程Web服务器(它使用了Java的HttpURLConnection API接口)的代码进行单元测试。我们特别展示了如何使用开源的Jetty来替换远程Web服务器。Jetty 可嵌入的特性让你能专注于替换Jetty的HTTP 请求处理器,而不是替换整个容器。我们通过替换Java的 HttpURLConnection类也阐述了一个更轻量级的解决方案。

下一章将介绍一种叫做mock objects的技术,这种技术支持细粒度单元测试。细粒度单元测试是完全通用的,并且(也是最好的一点)还能迫使你编写优秀的代码。虽然stub在一些情况中非常有用,但是有些人会觉得stub已经有些过时了,在过去多数人都认为测试应该是独立的,并且不应该修改已有的代码。新的mock objects策略不仅允许修改代码,而且还鼓励这一点。使用mock objects 不仅仅是一种单元测试策略,它更是一种编写代码的全新方式。

相关内容

文章评论

表情

共 0 条评论,查看全部
  • 这篇文章还没有收到评论,赶紧来抢沙发吧~