Java RESTful API集成测试

这篇文章将重点介绍为RESTful API(带有JSON有效负载)编写Java集成测试的基本原理和机制。

目的是对技术进行介绍,并为基本正确性编写一些测试。 这些示例将使用最新版本的GitHub REST API。

对于内部应用程序,这种测试通常将在持续集成过程中作为后期步骤运行,并在已部署REST API后使用它。

在测试REST资源时,通常应承担一些正交的职责,测试应重点关注:

  • HTTP 响应代码
  • 响应中的其他HTTP 标头
  • 有效负载 (JSON,XML)

每个测试应仅关注单个职责并包括单个声明。 专注于清晰的分离总是有好处的,但是当进行这种黑盒测试时,它就显得尤为重要,因为通常的趋势是在一开始就编写复杂的测试方案。

集成测试的另一个重要方面是遵守单一抽象原理–测试中的逻辑应以较高的层次编写。 诸如创建请求,将HTTP请求发送到服务器,处理IO等之类的细节不应内联而是通过实用程序方法来完成。

测试HTTP响应代码

@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()throws ClientProtocolException, IOException{// GivenString name = randomAlphabetic( 8 );HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );// WhenHttpResponse httpResponse = httpClient.execute( request );// ThenRestAssert.assertResponseCodeIs( httpResponse, 404 );
}

这是一个相当简单的测试,它验证基本的快乐路径在起作用,而不会增加测试套件的复杂性。 如果由于某种原因它失败了,那么在此URL修复之前,无需检查该URL的任何其他测试。 由于验证响应代码是集成测试套件中最常见的断言之一,因此将使用自定义断言 。

public static void assertResponseCodeIs( final HttpResponse response, final int expectedCode ){final int statusCode = httpResponse.getStatusLine().getStatusCode();assertEquals( expectedCode, statusCode );
}

测试HTTP响应的其他标头

@Test
public void givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson()throws ClientProtocolException, IOException{// GivenString jsonMimeType = "application/json";HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );// WhenHttpResponse response = this.httpClient.execute( request );// ThenString mimeType = EntityUtils.getContentMimeType( response.getEntity() );assertEquals( jsonMimeType, mimeType );
}

这样可以确保在请求用户详细信息时的响应实际上是JSON。 被测试功能有一个逻辑上的进展-首先是响应代码,以确保请求正常,然后是请求的mime类型,然后才是对实际JSON是否正确的验证。

测试HTTP响应的JSON有效负载

@Test
public void givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()throws ClientProtocolException, IOException{// GivenHttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );// WhenHttpResponse response = new DefaultHttpClient().execute( request );// ThenGitHubUser resource =RetrieveUtil.retrieveResourceFromResponse( response, GitHubUser.class );assertThat( "eugenp", Matchers.is( resource.getLogin() ) );
}

在这种情况下,我知道GitHub资源的默认表示形式是JSON,但通常应将响应的Content-Type标头与请求的Accept标头一起进行测试-客户端通过Accept请求特定的表示类型,服务器应该兑现。

测试工具

以下是使测试保持较高抽象水平的实用程序:

–使用JSON有效负载(或直接使用POJO)装饰HTTP请求:

public static < T >HttpEntityEnclosingRequest decorateRequestWithResource( final HttpEntityEnclosingRequest request, final T resource )throws IOException{Preconditions.checkNotNull( request );Preconditions.checkNotNull( resource );final String resourceAsJson = JsonUtil.convertResourceToJson( resource );return JsonUtil.decorateRequestWithJson( request, resourceAsJson );
}public static HttpEntityEnclosingRequest decorateRequestWithJson( final HttpEntityEnclosingRequest request, final String json )throws UnsupportedEncodingException{Preconditions.checkNotNull( request );Preconditions.checkNotNull( json );request.setHeader( HttpConstants.CONTENT_TYPE_HEADER, "application/json" );request.setEntity( new StringEntity( json ) );return request;
}

–从HTTP响应中检索JSON有效负载(或直接获取POJO):

public static String retrieveJsonFromResponse( final HttpResponse response )throws IOException{Preconditions.checkNotNull( response );return IOUtils.toString( response.getEntity().getContent() );
}public static < T >T retrieveResourceFromResponse( final HttpResponse response, final Class< T > clazz ) throws IOException{Preconditions.checkNotNull( response );Preconditions.checkNotNull( clazz );final String jsonFromResponse = retrieveJsonFromResponse( response );return ConvertUtil.convertJsonToResource( jsonFromResponse, clazz );
}

–从Java对象(PO​​JO)到JSON的转换实用程序:

public static < T >String convertResourceToJson( final T resource )throws IOException{Preconditions.checkNotNull( resource );return new ObjectMapper().writeValueAsString( resource );
}public static < T >T convertJsonToResource( final String json, final Class< T > clazzOfResource ) throws IOException{Preconditions.checkNotNull( json );Preconditions.checkNotNull( clazzOfResource );return new ObjectMapper().readValue( json, clazzOfResource );
}

依存关系

这些实用程序和测试利用了以下库,所有这些库都可以在Maven Central中使用:

  • Apache HttpCore和HttpClient
  • Apache Commons IO
  • Apache Commons Lang
  • 杰克逊
  • 番石榴
  • Hamcrest

结论

这只是完整的集成测试套件应有的一部分。 这些测试着重于确保REST API的基本正确性,而不涉及更复杂的场景,API的可发现性,对同一资源或其他更高级区域使用不同表示形式的情况。 我将在进一步的文章中讨论这些问题,同时在github上检出整个项目 。

参考:我们的JCG合作伙伴 Eugen Paraschiv在baeldung博客上 介绍了RESTful API的Java集成测试 。

相关文章 :
  • Tomcat 7上具有RESTeasy JAX-RS的RESTful Web服务-Eclipse和Maven项目
  • Spring3 RESTful Web服务
  • Spring 3使用JUnit 4进行测试– ContextConfiguration和AbstractTransactionalJUnit4SpringContextTests
  • 单元和集成测试的代码覆盖率
  • jqGrid,REST,AJAX和Spring MVC集成
  • JUnit 4.9(测试版3)中的规则
  • Java教程和Android教程列表

翻译自: https://www.javacodegeeks.com/2011/10/java-restful-api-integration-testing.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374208.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java警惕自增的陷阱

public class proposal{public static void main(String[] args) {int count0;for(int i0;i<10;i){countcount;}System.out.println(count);}}结果输出&#xff1a;0/*步骤一&#xff1a;JMV吧count值&#xff08;其值是0&#xff09;拷贝到临时变量区&#xff1b;步骤二:co…

[LindCode] Binary Tree Postorder Traversal

Binary Tree Postorder Traversal Given a binary tree, return the postorder traversal of its nodes values. Example Given binary tree {1,#,2,3}, 1\2/3return [3,2,1]. Challenge Can you do it without recursion? SOLUTION 1: recursion&#xff1a; 分治法解决之&am…

九齐NY8B072A单片机使用笔记(一)TIMER0定时器

先上代码 //8bit count up , max 0xFF void Ny8b072a_Timer0_Init(void) {PCON1 C_TMR0_Dis; // Disable Timer0//1 * (255 - 5) 250usTMR0 5; // Load 0x00 to TMR0 (Initial Timer0 register)//16M 2T Div8 1usT0MD C_PS0_TMR0 | C_PS0_Div8 ; // Prescaler0 is assign…

python菜鸟教程split_Python split()方法

网页地址解析&#xff1a; #codingutf-8 str"http://www.runoob.com/python/att-string-split.html" print("0:%s"%str.split("/")[-1]) print("1:%s"%str.split("/")[-2]) print("2:%s"%str.split("/"…

金山毒霸垃圾清理

金山毒霸-垃圾清理-单文件封装,清洁洁癖的爱好&#xff01; 实话&#xff0c;金山的软件确实不错。展望金山可以在软件行业&#xff0c;做出让世界都使用的。为国人扛起一片天 下载地址&#xff1a; http://pan.baidu.com/s/1dFa7GdV转载于:https://www.cnblogs.com/xiaochina/…

并发优化–减少锁粒度

在高负载多线程应用程序中&#xff0c;性能非常重要。 开发人员必须意识到并发问题才能获得更好的性能。 当我们需要并发时&#xff0c;我们通常拥有必须由两个或更多线程共享的资源。 在这种情况下&#xff0c;我们有一个竞争条件 &#xff0c;其中只有一个线程&#xff08;在…

Java1.5增加了新特性:可变参数

/*Java 可变参数Java1.5增加了新特性&#xff1a;可变参数&#xff1a;适用于参数个数不确定&#xff0c;类型确定的情况&#xff0c;java把可变参数当做数组处理。注意&#xff1a;可变参数必须位于最后一项。当可变参数个数多余一个时&#xff0c;必将有一个不是最后一项&…

C语言代码规范(十)花里胡哨代码鉴赏

一、宏定义篇 1、作者的目的是防止GPIO口赋值超过1。但是有明显自觉高人一等&#xff0c;瞧不起读者的感觉。 uint8_t not_func(uint8_t sw) {return (sw?1:0); }#define LED1(sw) PA12not_func(sw)修改建议&#xff1a; #define LED1 PA12 #define LED_ON 0 #de…

python-break循环中断

Python break语句&#xff0c;就像在C语言中&#xff0c;打破了最小封闭for或while循环。 break语句用来终止循环语句&#xff0c;即循环条件没有False条件或者序列还没被完全递归完&#xff0c;也会停止执行循环语句。 break语句用在while和for循环中。 如果您使用嵌套循环&am…

正则表达式验证六位数以上数字,符号,字母任意两种混合的密码验证策略

^(?![0-9]$)(?![a-zA-Z]$)(?!([^(0-9a-zA-Z)]|[\(\)])$)([^(0-9a-zA-Z)]|[\(\)]|[a-zA-Z]|[0-9]){6,}$这个正则如果是单独的数字&#xff0c;字符和符号&#xff0c;是不能通过的&#xff0c;少于6位也不行&#xff0c;希望大家可以继续验证正确性吧转载于:https://www.cnbl…

python post请求实例_Python使用requests发送POST请求实例代码

本文研究的主要是Python使用requests发送POST请求的相关内容&#xff0c;具体介绍如下。 一个http请求包括三个部分&#xff0c;为别为请求行&#xff0c;请求报头&#xff0c;消息主体&#xff0c;类似以下这样&#xff1a; 请求行 请求报头 消息主体 HTTP协议规定post提交的数…

Java Micro-Benchmarking:如何编写正确的基准

几个月前&#xff0c;我写了一篇文章比较循环的短索引的性能 。 我问自己关于使用短裤作为循环迭代次数很少的循环的性能。 在Java语言中&#xff0c;所有对整数的操作都是int进行的。 因此&#xff0c;如果我们使用short作为循环索引&#xff0c;则在每次迭代时都将进行类型转…

新唐M031学习笔记(一)定时器基础计数应用

先上代码 void Hw_Timer0_Init(void) {//20:100ms 200:10ms 2000:1ms 20000:100us 200000:10us TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 200000);/* Update prescale to set proper resolution. */TIMER_SET_PRESCALE_VALUE(TIMER0, 1); /* Enable Timer0 interrupt */TI…

java三元操作符注意

/* 三元操作符的类型务必一致 */ public class proposal_3 {public static void main(String[] args) {int i80;String sString.valueOf(i<90?90:100);String s1String.valueOf(i<90?90:100.0);if(s.equals(s1))System.out.println("s和s1相等&#xff01;"…

缓解口臭可以喝一种水

河南中医学院第一附属医院耳鼻喉科主任医师梅祥胜点评&#xff1a;通常情况下&#xff0c;口臭跟脾胃湿热有关。中医讲&#xff1a;“胃主受纳&#xff0c;脾主运化&#xff1b;胃气主降&#xff0c;使饮食物及 其糟粕得以下行&#xff0c;脾气主升&#xff0c;则饮食物之精华得…

asp.net+mvc+easyui+sqlite 简单用户系统学习之旅(二)—— easyui的简单实用

下面开始在UserManager.Web中利用easyUI构建web。 1. 先删除自带的controllers、models和views&#xff08;里面的shared和web.config可以保存&#xff09;下面的文件 2. 要利用easyUI&#xff0c;首先去网上下载jquery-easyui-1.3.2.zip&#xff0c;同时下载一份EasyUI-1.3.2.…

adc如何获取周期_LOL:千珏拥有ADC最需要的位移和无敌能力,为什么没人用她打下路?...

— 点击蓝字 关注我们 —英雄联盟自国服上线以来&#xff0c;已经陪伴玩家走过了9个年头&#xff0c;目前英雄联盟中的英雄数量已经达到了151位&#xff0c;每一位都各具特色。千珏是一位深受玩家们喜爱的英雄&#xff0c;其在官方英雄的定位中&#xff0c;属于打野英雄&#x…

航顺HK32F030MF4P6 RST作GPIO SWCLK作EXTI5 SWDIO作ADC_AIN0

老习惯&#xff0c;先上代码 void Hw_Input_Chage_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_IOMUX, ENABLE);GPIOMUX->NRST_PIN_KEY (uint32_t)(0x00005AE1); //KEY…

centos7.2下编译安装git

centos最新的7.2版本&#xff0c;git居然是1.8&#xff0c;而最新的git版本是2.9 差的太多了&#xff0c;何况git2.0后有大更新。于是&#xff0c;我决定编译安装。中间有一点小破折&#xff0c;记录一下&#xff0c;备忘。 1&#xff0c;下载最新的源码&#xff0c;网址&#…

java务必让常量的值在运行期保持不变

/* 常量就是常量&#xff0c;在编译期就必须确定其值&#xff0c;不应该在运行期更改&#xff0c;否则程序的可读性会非常差 */public class proposal_2 {interface Const{public static final int RAND_CONSTnew Random().nextInt();}public static void main(String[] arg…