为了说明stub能做什么,我们先来为一个简单的应用程序构建一些stub,这个应用程序根据URL 打开一个 HTTP连接,同时读取其中的信息。图6.1显示了一个应用程序示例(只有一个webclient.getContent方法),它通过HTTP 连接远程的Web资源。远程的Web资源是一个servlet,它会产生一个 HTML 响应。图6.1中的 Web资源就是我们在stub定义中所提到的“真实的代码”。
图6.1 本示例打开一个HTTP连接来连接远程Web资源,
该 Web资源就是stub定义中的“真实的代码”。
在这一章中,我们的目标是通过使用stub替换远程Web资源来对getcontent方法进行单元测试,如图6.2所示。你可以使用stub替换servlet Web资源,返回一个简单的HTML页,无论你对TestWebClient测试用例需要什么。这个方法允许你独立地测试实现Web资源(它们依次调用执行链上的几个其他对象,甚至还有数据库)的getcontent方法。
图6.2 添加一个测试用例并使用一个stub来代替真实的 Web 资源
使用stub要注意的重点是,我们并没有修改getContent来接受stub。对于待测的应用程序来说,这个变化是透明的。为了允许使用stub,目标代码需要拥有一个定义完善的接口,并且允许插入不同的实现(在我们这个示例中,就是 stub)中。在如图6.1所示的示例中,接口是公共抽象类java.net.URLConnection,这个类清楚地将页面的实现与它的调用者隔离开来了。
我们以一个简单的HTTP 连接示例来看一下stub是如何运行的吧。来自示例应用程序的代码6.1显示了一个代码片段,它为给定的URL 打开 HTTP连接,并读取在URL上找到的信息。想象一下,这个方法就是你想对其进行单元测试的一个大项目的一部分。
我们从使用HttpURLconnection类打开一个HTTP连接开始1,然后我们读取流内容,直到没有内容可读为止②。如果发生一个错误,我们就返回null3。也许有人会认为更好的实现应该是抛出一个异常。但是对于测试目的来说,返回null是不错的。
在这个示例应用程序中,有两种可能的情况:远程Web服务器(如图6.1所示)可能位于开发平台的外围(如在合作站点上),或者它本身可能就是程序配置的平台的一部分。但是在这两种情况中,为了能够对WebClient类进行单元测试,你都需要在开发平台中引人一个服务器。一个相对简单的解决方案是安装一个Apache测试服务器,并将一些测试Web页面存放在Apache测试服务器的文件根目录中。这就是典型的、广泛采用的使用stub替代Web资源的解决方案。
但是它也有几个缺点,如表6.1所示。
幸运的是,有一个更加简单的解决方案;使用嵌入式 Web服务器。因为我们在Java中进行测试,所以最容易的选择就是使用可以嵌入测试用例类的Java Web服务器。为了这个明确的目的,你可以使用免费的、开源的Jetty 服务器。在本书中,我们使用Jetty来建立stub。关于Jetty的更多信息,可以访问http://www.eclipse.org/jettyl。
我们之所以选择使用Jetty,是因为它的运行速度很快(这在运行测试时非常重要),它是轻量级的,并且你的测试用例能够通过程序来控制它。此外,Jetty还是一个非常优秀的 Web、Servlet和JSP容器,你可以在实际生产中使用它。虽然在大部分的测试中,你很少会用到Jetty的这一功能,但是使用最好的技术总是不错的。
使用Jetty 可以让你消除上文所提到的缺点:JUnit测试用例启动了服务器,所有的测试都在同一位置使用Java编写,并且测试集的自动执行也不再是个问题。得益于Jetty的模块性,实践过程中真正的要点在于,仅仅使用stub替换Jetty处理器,而不是彻底替换整个服务器。
为了更好地理解如何从测试中建立和控制Jetty,我们来实现一个简单的示例。代码6.2显示了如何从 Java中启动Jetty,以及如何定义一个根目录(/)来启动服务文件。
我们从创建Jetty Server对象①开始,并在构造函数中指定使用哪一个端口来接收HTTP请求(端口8080)。然后,我们创建了一个Context对象②来处理HTTP请求并把它们传递给不同的处理器中。我们将上下文映射到已创建的服务器实例和根目录(URL中。setResourceBase方法设置文档根目录以提供资源。在下一行代码中,我们为根目录添加了一个 ResourceHandler 处理器,使之能提供文件系统中的文件。因为如果我们试图列出目录中的内容,这个处理器就会返回一个HTTP 403-Forbidden 错误,所以我们指定资源基础是一个文件。在这个例子中,我们指定pom.xml文件在项目的目录中。最后,我们启动服务器③。
如果你启动代码6.2中的程序,并在浏览器的地址栏中输人 http:/localhost:8080,你应该就能看到pom.xml文件的具体内容了(如图6.3所示)。
图6.3 在浏览器中测试JettySample类
图6.3显示了打开浏览器访问http://localhost:8080之后运行代码6.2的结果。
现在你已经了解了如何将Jetty 作为一个嵌入式服务器来运行,接下来我们将要介绍如何使用stub替换服务器资源。