Skip to content

Commit

Permalink
Merge pull request #134 from aguibert/restAssured
Browse files Browse the repository at this point in the history
Integration with REST-assured
  • Loading branch information
aguibert authored Jan 20, 2020
2 parents b3eb3fd + ac8e236 commit 2503a15
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 IBM Corporation and others
* Copyright (c) 2019,2020 IBM Corporation and others
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -21,6 +21,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
Expand All @@ -44,15 +45,16 @@
*/
class MicroShedTestExtension implements BeforeAllCallback {

static final Logger LOGGER = LoggerFactory.getLogger(MicroShedTestExtension.class);
static final Logger LOG = LoggerFactory.getLogger(MicroShedTestExtension.class);

@Override
public void beforeAll(ExtensionContext context) throws Exception {
Class<?> testClass = context.getRequiredTestClass();
ApplicationEnvironment config = ApplicationEnvironment.load();
LOGGER.info("Using ApplicationEnvironment class: " + config.getClass().getCanonicalName());
LOG.info("Using ApplicationEnvironment class: " + config.getClass().getCanonicalName());
config.applyConfiguration(testClass);
config.start();
configureRestAssured(config);
injectRestClients(testClass);
}

Expand All @@ -79,7 +81,7 @@ private static void injectRestClients(Class<?> clazz) {
Object restClient = rcBuilder.build(restClientField.getType());
try {
restClientField.set(null, restClient);
LOGGER.debug("Injected rest client for " + restClientField);
LOG.debug("Injected rest client for " + restClientField);
} catch (Exception e) {
throw new ExtensionConfigurationException("Unable to set field " + restClientField, e);
}
Expand All @@ -99,14 +101,60 @@ private static String createJwtIfNeeded(Field restClientField) {
return null;
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private static void configureRestAssured(ApplicationEnvironment config) {
Class<?> RestAssured = tryLoad("io.restassured.RestAssured");
if (RestAssured == null)
return;

try {
URL appURL = new URL(config.getApplicationURL());
String baseURI = appURL.getProtocol() + "://" + appURL.getHost();
int port = appURL.getPort();
String basePath = appURL.getPath();
LOG.info("Configuring RestAssured with baseURI=" + baseURI + " port=" + port + " basePath=" + basePath);

RestAssured.getField("baseURI").set(null, baseURI);
RestAssured.getField("basePath").set(null, basePath);
RestAssured.getField("port").set(null, port);
} catch (Exception e) {
LOG.warn("Unable to configure REST Assured because of: " + e.getMessage(), e);
}

try {
// Configure JSONB as the JSON object mapper by invoking:
// ObjectMapperType JSONB = ObjectMapperType.JSONB;
// ObjectMapperConfig omConfig = ObjectMapperConfig.objectMapperConfig().defaultObjectMapperType(JSONB);
// RestAssured.config = RestAssured.config.objectMapperConfig(omConfig);
ClassLoader cl = MicroShedTestExtension.class.getClassLoader();
Class<Enum> ObjectMapperType = (Class<Enum>) Class.forName("io.restassured.mapper.ObjectMapperType", false, cl);
Object JSONB = Enum.valueOf(ObjectMapperType, "JSONB");
Class<?> ObjectMapperConfig = Class.forName("io.restassured.config.ObjectMapperConfig", false, cl);
Object omConfig = ObjectMapperConfig.getMethod("objectMapperConfig").invoke(null);
omConfig = omConfig.getClass().getMethod("defaultObjectMapperType", ObjectMapperType).invoke(omConfig, JSONB);
Class<?> RestAssuredConfig = Class.forName("io.restassured.config.RestAssuredConfig", false, cl);
Object raConfig = RestAssured.getField("config").get(null);
raConfig = RestAssuredConfig.getMethod("objectMapperConfig", ObjectMapperConfig).invoke(raConfig, omConfig);
RestAssured.getField("config").set(null, raConfig);
LOG.debug("Regsitered JSONB ObjectMapper for REST Assured");
} catch (IllegalArgumentException e) {
// Prior to RestAssured 4.2.0 the ObjectMapperType.JSONB enum is not available
LOG.debug("Unable to configure JSON-B object mapper for REST Assured", e);
} catch (Exception e) {
LOG.warn("Unable to configure JSON-B object mapper for REST Assured", e);
}
}

@SuppressWarnings("unchecked")
private static Optional<Class<? extends Annotation>> getMpRestClient() {
return Optional.ofNullable((Class<? extends Annotation>) tryLoad("org.eclipse.microprofile.rest.client.inject.RestClient"));
}

private static Class<?> tryLoad(String clazz) {
try {
return Optional.of((Class<? extends Annotation>) Class.forName("org.eclipse.microprofile.rest.client.inject.RestClient",
false,
MicroShedTestExtension.class.getClassLoader()));
return Class.forName(clazz, false, MicroShedTestExtension.class.getClassLoader());
} catch (ClassNotFoundException | LinkageError e) {
return Optional.empty();
return null;
}
}
}
106 changes: 106 additions & 0 deletions docs/features/14_RestAssured.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
layout: post
title: "REST Assured"
---

MicroShed Testing provides auto-configuration for when [REST Assured](https://github.com/rest-assured/rest-assured) is available on the test classpath. REST Assured is a Java DSL library for easy testing of REST services. It is more verbose than using a REST client, but offers more direct control over the request and response.f

## Enable REST Assured

To enable REST Assured, add the following dependency to your pom.xml:

```xml
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>
```

Any version of REST Assured will have basic integration with MicroShed Testing -- the application URL and port will be auto-configured.

As of REST Assured 4.2.0 or newer, a JSON-B based JSON ObjectMapper will be auto-configured.

Because of the auto-configuration, no specific configuration is required in your test classes.

## Example usage

Validating a simple `GET` request:

```java
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
// ...

@MicroShedTest
public class RestAssuredTest {

@Container
public static ApplicationContainer app = new ApplicationContainer()
.withAppContextRoot("/myservice");

@Test
public void testCreatePerson() {
given()
.queryParam("name", "Hank")
.queryParam("age", 45)
.contentType(JSON)
.when()
.post("/")
.then()
.statusCode(200)
.contentType(JSON);
}
}
```

It is also possible to send/receive POJOs with the JSON-B based ObjectMapper:

```java
@Test
public void testGetPerson() {
// First create the Person
long bobId = given()
.queryParam("name", "Bob")
.queryParam("age", 24)
.contentType(JSON)
.when()
.post("/")
.then()
.statusCode(200)
.contentType(JSON)
.extract()
.as(long.class);

// Validate new created Person can be retrieved
Person bob = given()
.pathParam("personId", bobId)
.when()
.get("/{personId}")
.then()
.statusCode(200)
.contentType(JSON)
.extract()
.as(Person.class);
assertEquals("Bob", bob.name);
assertEquals(24, bob.age);
assertNotNull(bob.id);
}
```

For a complete working example, see the [RestAssuredTest class](https://github.com/MicroShed/microshed-testing/blob/master/sample-apps/everything-app/src/test/java/org/example/app/RestAssuredTest.java)

## Auto-configuration override

If you would like to use a different JSON ObjectMapper besides the default (JSON-B/Yasson), you can run the following code in your test initialization flow:

```java
import io.restassured.RestAssured;
import io.restassured.config.ObjectMapperConfig;
import io.restassured.mapper.ObjectMapperType;
// ...

ObjectMapperConfig omConfig = ObjectMapperConfig.objectMapperConfig().defaultObjectMapperType(ObjectMapperType.JACKSON_2);
RestAssured.config = RestAssured.config.objectMapperConfig(omConfig);
```
1 change: 1 addition & 0 deletions docs/features/98_Examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Sometimes code is worth a thousand words. Here are some pointers to working exam

- [Basic JAX-RS application using Gradle](https://github.com/MicroShed/microshed-testing/tree/master/sample-apps/jaxrs-json)
- [Basic JAX-RS application using Maven](https://github.com/MicroShed/microshed-testing/tree/master/sample-apps/maven-app)
- [Basic JAX-RS application using REST Assured](https://github.com/MicroShed/microshed-testing/blob/master/sample-apps/everything-app/src/test/java/org/example/app/RestAssuredTest.java)
- [JAX-RS and JDBC applicaiton using a PostgreSQL database](https://github.com/MicroShed/microshed-testing/tree/master/sample-apps/jdbc-app)
- [JAX-RS application secured with MP JWT](https://github.com/MicroShed/microshed-testing/tree/master/sample-apps/jaxrs-mpjwt)
- [JAX-RS and MongoDB application that depends on an external REST service](https://github.com/MicroShed/microshed-testing/tree/master/sample-apps/everything-app)
Expand Down
1 change: 1 addition & 0 deletions sample-apps/everything-app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
testCompile group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.29'
testCompile 'org.testcontainers:mockserver:1.12.3'
testCompile 'org.mock-server:mockserver-client-java:5.5.4'
testCompile 'io.rest-assured:rest-assured:4.2.0'
testImplementation 'org.junit.jupiter:junit-jupiter:5.5.2'
}

Expand Down
Loading

0 comments on commit 2503a15

Please sign in to comment.