待测试类: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配置的过程。
 */
@Ignore
public 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实战》笔记

利用stub技术进行单元测试的更多相关文章

  1. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  2. VC中利用多线程技术实现线程之间的通信

    当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...

  3. 利用neon技术对矩阵旋转进行加速(2)

    上次介绍的是顺时针旋转90度,最近用到了180度和270度,在这里记录一下. 1.利用neon技术将矩阵顺时针旋转180度: 顺时针旋转180度比顺时针旋转90度容易很多,如下图 A1 A2 A3 A ...

  4. 利用neon技术对矩阵旋转进行加速

    一般的矩阵旋转操作都是对矩阵中的元素逐个操作,假设矩阵大小为m*n,那么时间复杂度就是o(mn).如果使用了arm公司提供的neon加速技术,则可以并行的读取多个元素,对多个元素进行操作,虽然时间复杂 ...

  5. 利用jsp技术实现用户注册

    利用jsp技术实现用户注册,包含register.html和register_check.jsp页面代码​1. [代码]J2EE实验    <!DOCTYPE html PUBLIC " ...

  6. 利用Docker技术实现UDP广播效果(网络编程python版)

    docker的安装见官方文档 我使用的系统为Ubuntu16.04 Ubuntu系统安装docker文档地址:https://docs.docker.com/engine/installation/l ...

  7. (转)iOS Wow体验 - 第五章 - 利用iOS技术特性打造最佳体验

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第五章译文精选,其余章节将陆续放出.上一篇:Wow ...

  8. 京东无人超市的成长之路 如何利用AI技术在零售业做产品创新?

    随着消费及用户体验的需求升级.人货场的运营效率需求提升.人工智能技术的突破以及零售基础设施的变革等因素共同推动了第四次零售革命的到来,不仅在国内,国外一线巨头互联网亚马逊等企业都在研发无人驾驶.无人超 ...

  9. 利用jsonrpc技术包装uiautomator

    昨天一天在网上搜索解决上一篇文章中的exception: monkeyrunner内置uiautomator出错的原因 尽管没找到解决办法.可是让我无意中发现了一个好工具,比sl4a更好用的工具.直接 ...

随机推荐

  1. CSS计数器:counter

    最近的需求,明星字体销售排行榜中,需要对字体的销售情况进行排序. 在早期,只有ol和ul可以对子元素li进行排序:如果不使用这两个标签,就由前台开发去手动填写序号. 当然,在这个需求中,数据不是实时更 ...

  2. C#调用Microsoft.DirectX.DirectSound.dll时出错

    1.修改工程的编译选项.我的开发运行环境是Windows 10 x64系统.需要修改一下工程的编译选项,把AnyCPU改成x86的. 未能加载文件或程序集“Microsoft.DirectX.Dire ...

  3. 领域驱动设计(DDD)的实践经验分享之ORM的思考

    原文:领域驱动设计(DDD)的实践经验分享之ORM的思考 最近一直对DDD(Domain Driven Design)很感兴趣,于是去网上找了一些文章来看看,发现它确实是个好东西.于是我去买了两本关于 ...

  4. 华为ensp的安装和使用

    去年学完了Cisco的路由交换,从CCNA学到CCIE.学完之后才发现,整个国内市场好像更倾向于使用华为.H3C这类国有网络设备厂商.不过还好,至少网络的基础理论知识是相同的,于是买了基本关于HUAW ...

  5. Linux可以把vmdk当做磁盘加载进去

    VMware虚拟机由于停电,无法启动MAC系统 下午的时候,正在开发ios app,结果停电了.当时还不知道,伴随而来的灾难竟然折腾了好几天,真是心力交瘁. 我是在VMware虚拟机下装的Mac os ...

  6. Zookeeper zkui-zookeeper图形化管理工具

    zkui zkui是一个Zookeeper可视化管理工具. Github:https://github.com/DeemOpen/zkui zkui安装 1.Git拉取代码 #git clone ht ...

  7. B/s发展情况真的可以用日新月异来形容

    做c/s也做b/s.从发展情况看,B/s发展情况真的可以用日新月异来形容,但确实也有些绕着路走的框架,不如delphi层次结构清晰. 如果前端用过angularjs等类似框架,则已经相当接近c/s的水 ...

  8. windows-qt 使用mingw编译c++boost并使用

    一.boost是一个准标准库,相当于STL的延续和扩充,它的设计理念和STL比较接近,都是利用泛型让复用达到最大化.不过对比STL,boost更加实用.STL集中在算法部分,而boost包含了不少工具 ...

  9. FilterFactory是一款将图片转换成SVG的在线生成工具。

    FilterFactory是一款将图片转换成SVG的在线生成工具. FilterFactory 彩蛋爆料直击现场 FilterFactory是一款将图片转换成SVG的在线生成工具.

  10. QT5.7静态编译(使用VS2013与VS2015编译,XP可用,有详细configure脚本。VS下Qt插件的配置。编译选项加上-mp可以开启多线程编译,编译速度提高2倍以上)

    http://blog.csdn.net/u011964923/article/details/52886908 configure -confirm-license -opensource -pla ...