注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

0与1构筑世界,程序员创造时代

软件架构设计 Java编程

 
 
 

日志

 
 

使用Jetty实现Http Server Mock作单元测试 | Testing with Jetty  

2014-05-05 20:15:41|  分类: Java |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
使用Jetty实现Http Server Mock作单元测试 - 傲风 - 0与1构筑世界,程序员创造时代

在研发过程中发现许多模块对外部系统的调用并没有沉淀成专门的客户端,代码中直接调用URL发送请求和获取响应内容,导致做单元测试的时候非常麻烦。 特别是对已有系统做改造的时候,要先写单元测试用例,保证后续的重构和修改不偏离原来的业务需求。

这样问题就来了:该如何模拟外部系统返回各种正常和异常的响应内容呢? 办法总是有的,这里就用Jetty实现Http Server Mock,模拟服务端返回各种响应数据。

预备

业务示例代码

源码下载

package cn.aofeng.demo.jetty;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.io.IOUtils;

/**
 * 抓取页面内容。
 * 
 * @author <a href="mailto:aofengblog@163.com">聂勇</a>
 */
public class HttpGet {

    public String getSomeThing(String urlStr) throws IOException {
        URL url = new URL(urlStr);
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
        urlConn.setConnectTimeout(3000);
        urlConn.setRequestMethod("GET");
        urlConn.connect();

        InputStream ins = null;
        try {
            if (200 == urlConn.getResponseCode()) {
                ins = urlConn.getInputStream();
                ByteArrayOutputStream outs = new ByteArrayOutputStream(1024);
                IOUtils.copy(ins, outs);
                return outs.toString("UTF-8");
            }
        } catch (IOException e) {
            throw e;
        } finally {
            IOUtils.closeQuietly(ins);
        }

        return null;
    }

}

用Jetty实现的Http Server Mock

源码下载

package cn.aofeng.demo.jetty;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

/**
 * HTTP服务器MOCK,可用于单元测试时模拟HTTP服务器的响应。
 * 
 * @author <a href="mailto:aofengblog@163.com">聂勇</a>
 */
public class HttpServerMock {

    public final static int DEFAULT_PORT = 9191;
    public final static String DEFAULT_CONTENT_TYPE = "application/json";
    public final static int DEFAULT_STATUS_CODE=HttpServletResponse.SC_OK;

    private Server _httpServer;
    private int _port;

    public HttpServerMock() {
        _port = DEFAULT_PORT;
    }

    public HttpServerMock(int port) {
        _port = port;
    }

    /**
     * 启动Jetty服务器。默认的响应status code为"200",content type为"application/json"。
     * @param content 响应内容
     */
    public void start(String content) throws Exception {
        start(content, DEFAULT_CONTENT_TYPE, DEFAULT_STATUS_CODE);
    }

    /**
     * 启动Jetty服务器。默认的响应status code为"200"。
     * @param content 响应内容
     * @param contentType 响应内容的MIME类型
     */
    public void start(String content, String contentType) throws Exception {
        start(content, contentType, DEFAULT_STATUS_CODE);
    }

    /**
     * 启动Jetty服务器。
     * @param content 响应内容
     * @param contentType 响应内容的MIME类型
     * @param statuCode 响应状态码
     */
    public void start(String content, String contentType, 
            int statuCode) throws Exception {
        _httpServer = new Server(_port);
        _httpServer.setHandler(createHandler(content, contentType, statuCode));
        _httpServer.start();
    }

    /**
     * 停止Jetty服务器。
     */
    public void stop() throws Exception {
        if (null != _httpServer) {
            _httpServer.stop();
            _httpServer = null;
        }
    }

    private Handler createHandler(final String content, final String contentType, 
            final int statusCode) {
        return new AbstractHandler() {
            @Override
            public void handle(String target, Request baseRequest, HttpServletRequest request,
                    HttpServletResponse response) throws IOException, ServletException {
                response.setContentType(contentType);
                response.setStatus(statusCode);
                baseRequest.setHandled(true);
                response.getWriter().print(content);
            }
        };
    }

}

单元测试代码

源码下载

package cn.aofeng.demo.jetty;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * {@link HttpGet}的单元测试用例。
 * 
 * @author <a href="mailto:aofengblog@163.com">聂勇</a>
 */
public class HttpGetTest {

    private HttpServerMock _mock;
    private HttpGet _httpGet = new HttpGet();

    @Before
    public void setUp() throws Exception {
        _mock = new HttpServerMock();
    }

    @After
    public void tearDown() throws Exception {
        if (null != _mock) {
            _mock.stop();
        }
    }

    /**
     * 用例:响应状态码为200且有响应内容。
     */
    @Test
    public void testGetSomeThing4Success() throws Exception {
        String response = "Hello, The World!";
        _mock.start(response, "text/plain");

        String content = _httpGet.getSomeThing("http://localhost:9191/hello");
        assertEquals(response, content);
    }

    /**
     * 用例:响应状态码为非200。
     */
    @Test
    public void testGetSomeThing4Fail() throws Exception {
        String response = "Hello, The World!";
        _mock.start(response, "text/plain", 500);

        String content = _httpGet.getSomeThing("http://localhost:9191/hello");
        assertNull(content);
    }

}

<正文结束>

文章声明


作者:傲风(aofengblog@163.com)       编写时间:2014年05月05日

网址:http://aofengblog.blog.163.com

作者保留所有权利,转载请保留文章全部内容或者说明原作者和转载地址!

  评论这张
 
阅读(1173)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017