利用stub技术进行单元测试
待测试类: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技术进行单元测试的更多相关文章
- [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
- VC中利用多线程技术实现线程之间的通信
当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...
- 利用neon技术对矩阵旋转进行加速(2)
上次介绍的是顺时针旋转90度,最近用到了180度和270度,在这里记录一下. 1.利用neon技术将矩阵顺时针旋转180度: 顺时针旋转180度比顺时针旋转90度容易很多,如下图 A1 A2 A3 A ...
- 利用neon技术对矩阵旋转进行加速
一般的矩阵旋转操作都是对矩阵中的元素逐个操作,假设矩阵大小为m*n,那么时间复杂度就是o(mn).如果使用了arm公司提供的neon加速技术,则可以并行的读取多个元素,对多个元素进行操作,虽然时间复杂 ...
- 利用jsp技术实现用户注册
利用jsp技术实现用户注册,包含register.html和register_check.jsp页面代码1. [代码]J2EE实验 <!DOCTYPE html PUBLIC " ...
- 利用Docker技术实现UDP广播效果(网络编程python版)
docker的安装见官方文档 我使用的系统为Ubuntu16.04 Ubuntu系统安装docker文档地址:https://docs.docker.com/engine/installation/l ...
- (转)iOS Wow体验 - 第五章 - 利用iOS技术特性打造最佳体验
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第五章译文精选,其余章节将陆续放出.上一篇:Wow ...
- 京东无人超市的成长之路 如何利用AI技术在零售业做产品创新?
随着消费及用户体验的需求升级.人货场的运营效率需求提升.人工智能技术的突破以及零售基础设施的变革等因素共同推动了第四次零售革命的到来,不仅在国内,国外一线巨头互联网亚马逊等企业都在研发无人驾驶.无人超 ...
- 利用jsonrpc技术包装uiautomator
昨天一天在网上搜索解决上一篇文章中的exception: monkeyrunner内置uiautomator出错的原因 尽管没找到解决办法.可是让我无意中发现了一个好工具,比sl4a更好用的工具.直接 ...
随机推荐
- git pull和fetch的区别
详解git pull和git fetch的区别: - weixin_41975655的博客 - CSDN博客 https://blog.csdn.net/weixin_41975655/article ...
- MongoDB centos安装问题 error while loading shared libraries: libnetsnmpmibs.so.31
安装mongodb-linux-x86_64-enterprise-rhel70-4.0.5 cd /usr/mongodb tar -zxvf mongodb-linux-x86_64-enter ...
- 用Delphi实现文件下载的几种方法(三种使用控件的方法)
有个API就是UrlDownloadToFile.不仅如此,Delphi的一些控件也可以轻松实现下载,如NMHTTP,指定NMHTTP1.InputFileMode := ture; 指定Body为本 ...
- 使用 Elastic Stack 来监控和调优 Golang 应用程序
Golang 因为其语法简单,上手快且方便部署正被越来越多的开发者所青睐,一个 Golang 程序开发好了之后,势必要关心其运行情况,今天在这里就给大家介绍一下如果使用 Elastic Stack 来 ...
- 使用QPainter的drawPixmap()绘制多幅图片 good
众所周知,使用QLabel的setPixmap()就可以将图片显示出来,做视屏解码后显示也可以如此.但是为何我今天还要费力使用基函数drawPixmap()来做绘图?理由有这么些吧: 1.使用QLab ...
- Oracle 宣布 Java 7 生命周期终结
快速使用Romanysoft LAB的技术实现 HTML 开发Mac OS App,并销售到苹果应用商店中. <HTML开发Mac OS App 视频教程> 土豆网同步更新:http: ...
- 通过内核对象在服务程序和桌面程序之间通信的小问题 good
关于在通过 事件对象 在服务程序和普通桌面应用程序相互之间通信的问题,分类情况进行讨论:1.普通桌面应用程序中创建事件,服务程序中打开事件 XP的情况普通桌面应用程序中创建: m_hEvent = : ...
- 原生Js汉语拼音首字母匹配城市名/自动提示列表
根据城市的汉语名称首字母把城市排序,基本思路: 1.处理数据,按照需要的格式分别添加{HOT:{hot:[],ABCDEFG:{a:[1,2,3],b:[1,2,3]},HIGHLMN:{},OPQR ...
- Elasticsearch-head插件使用小结
1.ElasticSearch-head是什么? ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasti ...
- XGBoost类库使用小结
在XGBoost算法原理小结中,我们讨论了XGBoost的算法原理,这一片我们讨论如何使用XGBoost的Python类库,以及一些重要参数的意义和调参思路. 本文主要参考了XGBoost的Pytho ...