目的是对技术进行介绍,并为基本正确性编写一些测试。 这些示例将使用最新版本的GitHub REST API。
对于内部应用程序,这种测试通常将在持续集成过程中作为后期步骤运行,并在已部署REST API后使用它。
在测试REST资源时,通常应承担一些正交的职责,测试应重点关注:
- HTTP 响应代码
- 响应中的其他HTTP 标头
- 有效负载 (JSON,XML)
每个测试应仅关注单个职责并包括单个声明。 专注于清晰的分离总是有好处的,但是当进行这种黑盒测试时,它就显得尤为重要,因为通常的趋势是在一开始就编写复杂的测试方案。
集成测试的另一个重要方面是遵守单一抽象原理–测试中的逻辑应以较高的层次编写。 诸如创建请求,将HTTP请求发送到服务器,处理IO等之类的细节不应内联而是通过实用程序方法来完成。
测试HTTP响应代码
@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()
throws ClientProtocolException, IOException{
// Given
String name = randomAlphabetic( 8 );
HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );
// When
HttpResponse httpResponse = httpClient.execute( request );
// Then
RestAssert.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{
// Given
String jsonMimeType = "application/json";
HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
// When
HttpResponse response = this.httpClient.execute( request );
// Then
String mimeType = EntityUtils.getContentMimeType( response.getEntity() );
assertEquals( jsonMimeType, mimeType );
}
这样可以确保在请求用户详细信息时的响应实际上是JSON。 被测试功能有一个逻辑上的进展-首先是响应代码,以确保请求正常,然后是请求的mime类型,然后才是对实际JSON是否正确的验证。
测试HTTP响应的JSON有效负载
@Test
public void givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()
throws ClientProtocolException, IOException{
// Given
HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
// When
HttpResponse response = new DefaultHttpClient().execute( request );
// Then
GitHubUser 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对象(POJO)到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中使用:
结论
这只是完整的集成测试套件应有的一部分。 这些测试着重于确保REST API的基本正确性,而不涉及更复杂的场景,API的可发现性,对同一资源或其他更高级区域使用不同表示形式的情况。 我将在进一步的文章中讨论这些问题,同时在github上检出整个项目 。
参考:我们的JCG合作伙伴 Eugen Paraschiv在baeldung博客上 介绍了RESTful API的Java集成测试 。
翻译自: https://www.javacodegeeks.com/2011/10/java-restful-api-integration-testing.html