待测试类:WebClient:
import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;public class WebClient { /* 测试时的几个要点: 1.这个方法有两个出口: a.正常情况下,返回从服务器发回来的数据 b.如果getInputStream出错,返回一个null c.如果read出错,则返回一个null */ public String getContent (URL url){ StringBuffer content = new StringBuffer(); try{ HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setDoInput(true); InputStream in = connection.getInputStream(); ]; int count; != (count = in.read(buffer))) { content.append(,count)); } } catch (IOException e) { return null; } return content.toString(); }}
使用stub替换web资源的测试方法:
import org.junit.*;import org.mortbay.jetty.Server;import org.mortbay.jetty.handler.AbstractHandler;import org.mortbay.jetty.servlet.Context;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.OutputStream;import java.net.MalformedURLException;import java.net.URL;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertNull;/* 这种测试的核心思想就是,在我的测试过程中,搭建一个服务器,并在服务器上备上资源, ,我测试的方法,将会来访问我这个服务器,由于服务器中的资源是我自己准备的,所以 我可以对获取的资源的正确性进行判断。 这个测试用到的比价有技术含量的点有: 1.内嵌式服务器Jetty,这个我只需要研究一下Jetty配置自己的处理器 在正式开始整理之前,先回忆一下Tomcat中server.xml标签中说的一些关系: host中有许多个context engine中有许多个host service中有多个connector与一个Engine server中有多个service 我注意到一件事情,在使用Jetty时,作者总是先New出一个Server来,在Server中 设置端口号8080.这个已经和Tomcat有点不一样了。 其次Tomcat中是在web.xml中配置servlet与url的匹配,但是Jetty中是先New出一个 Context,然后将server及相应的url传入。最后调用setHandler()方法,设置该url 的处理类。 Tomcat中Context中的概念貌似和Jetty中的Context是类似的。我没有细究,但是我记得 在写Servlet时,我们总是用到一些Context中的参数。这部分以后再复习一下吧。 感觉把这些东西分析完了,自己也就理解了Jetty配置的过程。 */@Ignorepublic class TestWebClient { @BeforeClass public static void setUp() throws Exception { Server server = new Server(8080); TestWebClient t = new TestWebClient(); Context contextOkContext = new Context(server,"/textGetContentOk"); contextOkContext.setHandler(t.new TestGetContentOkHandler()); Context contextNotFoundContext = new Context(server, "/testGetContentNotFound"); contextNotFoundContext.setHandler(t.new TestGetContentNotFoundHandler()); server.setStopAtShutdown(true); server.start(); } private WebClient client; @Before public void ready(){ client = new WebClient(); } @Test public void testGetContentOk() throws Exception{ String result = client.getContent(new URL( "http://localhost:8080/textGetContentOk" )); assertEquals("It works",result); } @Test public void testGetContentNotFound() throws MalformedURLException { String result = client.getContent(new URL( "http://localhost:8080/testGetContentNotFound" )); assertNull(result); } @AfterClass public static void tearDown(){ } public class TestGetContentOkHandler extends AbstractHandler { public void handle(String s, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, int i) throws IOException, ServletException { OutputStream out = httpServletResponse.getOutputStream(); /* 这个地方的写法和我以前看到的不一样哦 */// ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer();// writer.write("It works");// writer.flush(); /* 感觉有必要把HTTP学习一下了 */// httpServletResponse.setIntHeader(HttpHeaders.CONTENT_LENGTH,writer.size());// writer.writeTo(out);// out.flush(); /* 我擦嘞,什么鬼,作者花式秀,结果还是错的,我这简简单单的一写,既然是对的 */ out.write("It works".getBytes("iso-8859-1")); out.flush(); } } public class TestGetContentNotFoundHandler extends AbstractHandler{ public void handle(String s, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, int i) throws IOException, ServletException { httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND); } }}
利用替换连接的方法:
import org.junit.BeforeClass;import org.junit.Ignore;import org.junit.Test;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.net.*;import static org.junit.Assert.assertEquals;/* 第二个方案:替换连接 该方案的核心技术是,利用Java中URL和HttpURLConnection类,我们引入 自定义的协议处理器来处理任何类型的通信协议。 技术要点: 1.为了实现一个自定义的URL协议处理器,你需要调用URL的setURLStreamHandlerFactory 方法,并传递给它一个自定义的URLStreamHandlerFactory。无论何时调用URL的 openConnection方法,都会调用URLStreamHandlerFactory类,返回一个 URLStreamHandler对象。(之前在getContent中调用这个方法时,得到的是一个connection 对象,现在说是一个URLStreamHandler对象,有点奇怪的哦。) public static void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) 设置应用程序的 URLStreamHandlerFactory。在一个给定的 Java 虚拟机中,此方法最多只能调用一次。 URLStreamHandlerFactory 实例用于从协议名称构造流协议处理程序。 public URLStreamHandler createURLStreamHandler(String protocol) 创建具有指定协议的新 URLStreamHandler 实例。 */public class TestWebClient1 { @BeforeClass public static void setUP(){ TestWebClient1 t = new TestWebClient1(); URL.setURLStreamHandlerFactory(t.new StubStreamHandlerFactory()); } @Test public void testGetContentOk() throws MalformedURLException { WebClient client = new WebClient(); String result = client.getContent(new URL("http://loalhost")); assertEquals("It works",result); } private class StubHttpURLConnection extends HttpURLConnection { private boolean isInput = true; public StubHttpURLConnection(URL u) { super(u); } /* 你想要的流里,我已经给你放好的东西。 */ @Override public InputStream getInputStream() throws IOException { if(!isInput){ new ProtocolException("Wrong in isInput..."); } ByteArrayInputStream bais = new ByteArrayInputStream( "It works".getBytes("ISO-8859-1") ); return bais; } public void disconnect() { } public boolean usingProxy() { return false; } public void connect() throws IOException { } } private class StubStreamHandlerFactory implements URLStreamHandlerFactory{ public URLStreamHandler createURLStreamHandler(String protocol) { return new StubHttpURLStreamHandler(); } } private class StubHttpURLStreamHandler extends URLStreamHandler{ protected URLConnection openConnection(URL u) throws IOException { return new StubHttpURLConnection(u); } }}
《Junit实战》笔记