Skip to content

Commit 8648314

Browse files
committed
replace restassured by vertx web client
reasons: * issues when trying to upgrade * sometimes weird error messages Side effect: realized that the self-signed cert we used did not have localhost as an allowed domain name, which is now also fixed (just re-signed the cert, the key pair stayed the same) Signed-off-by: Kai Helbig <kai.helbig@tngtech.com>
1 parent f3034ba commit 8648314

11 files changed

Lines changed: 646 additions & 550 deletions

File tree

build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ ext {
5454
keycloak_js_version = '25.0.6'
5555
mockito_version = '5.19.0'
5656
picocli_version = '4.7.7'
57-
restassured_version = '5.5.5'
5857
slf4j_version = '2.0.17'
5958
// starting from major version 5, vert.x needs Java 11+
6059
vertx_version = '4.5.18'

example-backend/build.gradle

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@ dependencies {
3333
implementation 'org.keycloak:keycloak-policy-enforcer:26.0.6'
3434
testImplementation project(':mock-junit')
3535
testImplementation project(':mock-junit5')
36-
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
37-
testImplementation "io.rest-assured:rest-assured:$restassured_version"
38-
testImplementation "io.rest-assured:json-path:$restassured_version"
39-
testImplementation "io.rest-assured:xml-path:$restassured_version"
36+
testImplementation "io.vertx:vertx-junit5:$vertx_version"
37+
testImplementation "io.vertx:vertx-web-client:$vertx_version"
4038
testImplementation "junit:junit:$junit4_version"
41-
testImplementation 'org.junit.jupiter:junit-jupiter'
4239
testImplementation "org.assertj:assertj-core:$assertj_version"
40+
testImplementation 'org.junit.jupiter:junit-jupiter'
41+
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
4342
}
4443

4544
jib {

example-backend/src/test/java/com/tngtech/keycloakmock/examplebackend/AuthenticationJUnit4Test.java

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22

33
import static com.tngtech.keycloakmock.api.ServerConfig.aServerConfig;
44
import static com.tngtech.keycloakmock.api.TokenConfig.aTokenConfig;
5-
import static org.hamcrest.Matchers.equalTo;
5+
import static org.assertj.core.api.Assertions.assertThat;
66

77
import com.tngtech.keycloakmock.junit.KeycloakMockRule;
8-
import io.restassured.RestAssured;
8+
import io.vertx.core.Vertx;
9+
import io.vertx.core.http.HttpResponseExpectation;
10+
import io.vertx.ext.web.client.HttpResponse;
11+
import io.vertx.ext.web.client.WebClient;
12+
import io.vertx.junit5.VertxTestContext;
13+
import java.util.concurrent.TimeUnit;
14+
import org.junit.After;
915
import org.junit.Before;
1016
import org.junit.ClassRule;
1117
import org.junit.Test;
@@ -26,68 +32,83 @@ public class AuthenticationJUnit4Test {
2632

2733
@LocalServerPort private int port;
2834

35+
private Vertx vertx;
36+
private VertxTestContext testContext;
37+
2938
@Before
3039
public void setup() {
31-
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
32-
RestAssured.port = port;
40+
vertx = Vertx.vertx();
41+
testContext = new VertxTestContext();
42+
}
43+
44+
@After
45+
public void shutdown() throws Throwable {
46+
assertThat(testContext.awaitCompletion(5, TimeUnit.SECONDS)).isTrue();
47+
if (testContext.failed()) {
48+
throw testContext.causeOfFailure();
49+
}
50+
vertx.close();
3351
}
3452

3553
@Test
3654
public void no_authentication_fails() {
37-
RestAssured.given().when().get("/api/hello").then().statusCode(401);
55+
WebClient.create(vertx)
56+
.get("/api/hello")
57+
.port(port)
58+
.send()
59+
.expecting(HttpResponseExpectation.SC_UNAUTHORIZED)
60+
.onComplete(testContext.succeedingThenComplete());
3861
}
3962

4063
@Test
4164
public void authentication_works() {
42-
RestAssured.given()
43-
.auth()
44-
.preemptive()
45-
.oauth2(mock.getAccessToken(aTokenConfig().withSubject("Awesome").build()))
46-
.when()
65+
WebClient.create(vertx)
4766
.get("/api/hello")
48-
.then()
49-
.statusCode(200)
50-
.and()
51-
.body(equalTo("Hello Awesome"));
67+
.port(port)
68+
.bearerTokenAuthentication(
69+
mock.getAccessToken(aTokenConfig().withSubject("Awesome").build()))
70+
.send()
71+
.expecting(HttpResponseExpectation.SC_OK)
72+
.map(HttpResponse::bodyAsString)
73+
.expecting("Hello Awesome"::equals)
74+
.onComplete(testContext.succeedingThenComplete());
5275
}
5376

5477
@Test
5578
public void authentication_without_role_fails() {
56-
RestAssured.given()
57-
.auth()
58-
.preemptive()
59-
.oauth2(mock.getAccessToken(aTokenConfig().build()))
60-
.when()
79+
WebClient.create(vertx)
6180
.get("/api/vip")
62-
.then()
63-
.statusCode(403);
81+
.port(port)
82+
.bearerTokenAuthentication(mock.getAccessToken(aTokenConfig().build()))
83+
.send()
84+
.expecting(HttpResponseExpectation.SC_FORBIDDEN)
85+
.onComplete(testContext.succeedingThenComplete());
6486
}
6587

6688
@Test
67-
public void authentication_with_role_works() {
68-
RestAssured.given()
69-
.auth()
70-
.preemptive()
71-
.oauth2(mock.getAccessToken(aTokenConfig().withRealmRole("vip").build()))
72-
.when()
89+
public void authentication_with_realm_role_works() {
90+
WebClient.create(vertx)
7391
.get("/api/vip")
74-
.then()
75-
.statusCode(200)
76-
.and()
77-
.body(equalTo("you may feel very special here"));
92+
.port(port)
93+
.bearerTokenAuthentication(mock.getAccessToken(aTokenConfig().withRealmRole("vip").build()))
94+
.send()
95+
.expecting(HttpResponseExpectation.SC_OK)
96+
.map(HttpResponse::bodyAsString)
97+
.expecting("you may feel very special here"::equals)
98+
.onComplete(testContext.succeedingThenComplete());
7899
}
79100

80101
@Test
81102
public void authentication_with_resource_role_works() {
82-
RestAssured.given()
83-
.auth()
84-
.preemptive()
85-
.oauth2(mock.getAccessToken(aTokenConfig().withResourceRole("server", "vip").build()))
86-
.when()
103+
WebClient.create(vertx)
87104
.get("/api/vip")
88-
.then()
89-
.statusCode(200)
90-
.and()
91-
.body(equalTo("you may feel very special here"));
105+
.port(port)
106+
.bearerTokenAuthentication(
107+
mock.getAccessToken(aTokenConfig().withResourceRole("server", "vip").build()))
108+
.send()
109+
.expecting(HttpResponseExpectation.SC_OK)
110+
.map(HttpResponse::bodyAsString)
111+
.expecting("you may feel very special here"::equals)
112+
.onComplete(testContext.succeedingThenComplete());
92113
}
93114
}

example-backend/src/test/java/com/tngtech/keycloakmock/examplebackend/AuthenticationJUnit5Test.java

Lines changed: 52 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,89 +2,91 @@
22

33
import static com.tngtech.keycloakmock.api.ServerConfig.aServerConfig;
44
import static com.tngtech.keycloakmock.api.TokenConfig.aTokenConfig;
5-
import static org.hamcrest.Matchers.equalTo;
65

76
import com.tngtech.keycloakmock.junit5.KeycloakMockExtension;
8-
import io.restassured.RestAssured;
9-
import org.junit.jupiter.api.BeforeEach;
7+
import io.vertx.core.Vertx;
8+
import io.vertx.core.http.HttpResponseExpectation;
9+
import io.vertx.ext.web.client.HttpResponse;
10+
import io.vertx.ext.web.client.WebClient;
11+
import io.vertx.junit5.VertxExtension;
12+
import io.vertx.junit5.VertxTestContext;
1013
import org.junit.jupiter.api.Test;
14+
import org.junit.jupiter.api.extension.ExtendWith;
1115
import org.junit.jupiter.api.extension.RegisterExtension;
1216
import org.springframework.boot.test.context.SpringBootTest;
1317
import org.springframework.boot.test.web.server.LocalServerPort;
1418

1519
@SpringBootTest(
1620
classes = ExampleBackendApplication.class,
1721
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
22+
@ExtendWith(VertxExtension.class)
1823
class AuthenticationJUnit5Test {
1924

2025
@RegisterExtension
2126
static KeycloakMockExtension mock =
2227
new KeycloakMockExtension(aServerConfig().withDefaultRealm("realm").build());
2328

24-
@LocalServerPort private int port;
25-
26-
@BeforeEach
27-
void setup() {
28-
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
29-
RestAssured.port = port;
30-
}
29+
@LocalServerPort int port;
3130

3231
@Test
33-
void no_authentication_fails() {
34-
RestAssured.given().when().get("/api/hello").then().statusCode(401);
32+
void no_authentication_fails(Vertx vertx, VertxTestContext testContext) {
33+
WebClient.create(vertx)
34+
.get("/api/hello")
35+
.port(port)
36+
.send()
37+
.expecting(HttpResponseExpectation.SC_UNAUTHORIZED)
38+
.onComplete(testContext.succeedingThenComplete());
3539
}
3640

3741
@Test
38-
void authentication_works() {
39-
RestAssured.given()
40-
.auth()
41-
.preemptive()
42-
.oauth2(mock.getAccessToken(aTokenConfig().withSubject("Awesome").build()))
43-
.when()
42+
void authentication_works(Vertx vertx, VertxTestContext testContext) {
43+
WebClient.create(vertx)
4444
.get("/api/hello")
45-
.then()
46-
.statusCode(200)
47-
.and()
48-
.body(equalTo("Hello Awesome"));
45+
.port(port)
46+
.bearerTokenAuthentication(
47+
mock.getAccessToken(aTokenConfig().withSubject("Awesome").build()))
48+
.send()
49+
.expecting(HttpResponseExpectation.SC_OK)
50+
.map(HttpResponse::bodyAsString)
51+
.expecting("Hello Awesome"::equals)
52+
.onComplete(testContext.succeedingThenComplete());
4953
}
5054

5155
@Test
52-
void authentication_without_role_fails() {
53-
RestAssured.given()
54-
.auth()
55-
.preemptive()
56-
.oauth2(mock.getAccessToken(aTokenConfig().build()))
57-
.when()
56+
void authentication_without_role_fails(Vertx vertx, VertxTestContext testContext) {
57+
WebClient.create(vertx)
5858
.get("/api/vip")
59-
.then()
60-
.statusCode(403);
59+
.port(port)
60+
.bearerTokenAuthentication(mock.getAccessToken(aTokenConfig().build()))
61+
.send()
62+
.expecting(HttpResponseExpectation.SC_FORBIDDEN)
63+
.onComplete(testContext.succeedingThenComplete());
6164
}
6265

6366
@Test
64-
void authentication_with_realm_role_works() {
65-
RestAssured.given()
66-
.auth()
67-
.preemptive()
68-
.oauth2(mock.getAccessToken(aTokenConfig().withRealmRole("vip").build()))
69-
.when()
67+
void authentication_with_realm_role_works(Vertx vertx, VertxTestContext testContext) {
68+
WebClient.create(vertx)
7069
.get("/api/vip")
71-
.then()
72-
.statusCode(200)
73-
.and()
74-
.body(equalTo("you may feel very special here"));
70+
.port(port)
71+
.bearerTokenAuthentication(mock.getAccessToken(aTokenConfig().withRealmRole("vip").build()))
72+
.send()
73+
.expecting(HttpResponseExpectation.SC_OK)
74+
.map(HttpResponse::bodyAsString)
75+
.expecting("you may feel very special here"::equals)
76+
.onComplete(testContext.succeedingThenComplete());
7577
}
7678

7779
@Test
78-
void authentication_with_resource_role_works() {
79-
RestAssured.given()
80-
.auth()
81-
.preemptive()
82-
.oauth2(mock.getAccessToken(aTokenConfig().withResourceRole("server", "vip").build()))
83-
.when()
80+
void authentication_with_resource_role_works(Vertx vertx, VertxTestContext testContext) {
81+
WebClient.create(vertx)
8482
.get("/api/vip")
85-
.then()
86-
.statusCode(200)
87-
.and()
88-
.body(equalTo("you may feel very special here"));
83+
.port(port)
84+
.bearerTokenAuthentication(
85+
mock.getAccessToken(aTokenConfig().withResourceRole("server", "vip").build()))
86+
.send()
87+
.expecting(HttpResponseExpectation.SC_OK)
88+
.map(HttpResponse::bodyAsString)
89+
.expecting("you may feel very special here"::equals)
90+
.onComplete(testContext.succeedingThenComplete());
8991
}
9092
}

mock-junit/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ dependencies {
44
api project(':mock')
55
implementation "com.google.code.findbugs:jsr305:$jsr305_version"
66
implementation "junit:junit:$junit4_version"
7-
testImplementation "io.rest-assured:rest-assured:$restassured_version"
7+
testImplementation "io.vertx:vertx-junit5:$vertx_version"
8+
testImplementation "io.vertx:vertx-web-client:$vertx_version"
89
testImplementation "org.assertj:assertj-core:$assertj_version"
910
}
Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.tngtech.keycloakmock.junit;
22

33
import static com.tngtech.keycloakmock.api.ServerConfig.aServerConfig;
4+
import static org.assertj.core.api.Assertions.assertThat;
45

5-
import io.restassured.RestAssured;
6-
import io.restassured.http.ContentType;
6+
import io.vertx.core.Vertx;
7+
import io.vertx.core.http.HttpResponseExpectation;
8+
import io.vertx.ext.web.client.WebClient;
9+
import io.vertx.junit5.VertxTestContext;
10+
import java.util.concurrent.TimeUnit;
11+
import org.junit.After;
712
import org.junit.Before;
813
import org.junit.Rule;
914
import org.junit.Test;
@@ -14,19 +19,33 @@ public class KeycloakMockRuleJunit4Test {
1419
public KeycloakMockRule keycloakMockRule =
1520
new KeycloakMockRule(aServerConfig().withRandomPort().build());
1621

22+
private Vertx vertx;
23+
private VertxTestContext testContext;
24+
private int port;
25+
1726
@Before
1827
public void setup() {
19-
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
20-
RestAssured.port = keycloakMockRule.getActualPort();
28+
vertx = Vertx.vertx();
29+
testContext = new VertxTestContext();
30+
port = keycloakMockRule.getActualPort();
31+
}
32+
33+
@After
34+
public void shutdown() throws Throwable {
35+
assertThat(testContext.awaitCompletion(5, TimeUnit.SECONDS)).isTrue();
36+
if (testContext.failed()) {
37+
throw testContext.causeOfFailure();
38+
}
39+
vertx.close();
2140
}
2241

2342
@Test
2443
public void mock_is_running() {
25-
RestAssured.when()
44+
WebClient.create(vertx)
2645
.get("/auth/realms/master/protocol/openid-connect/certs")
27-
.then()
28-
.statusCode(200)
29-
.and()
30-
.contentType(ContentType.JSON);
46+
.port(port)
47+
.send()
48+
.expecting(HttpResponseExpectation.SC_OK.and(HttpResponseExpectation.JSON))
49+
.onComplete(testContext.succeedingThenComplete());
3150
}
3251
}

mock-junit5/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ dependencies {
44
api project(':mock')
55
implementation "com.google.code.findbugs:jsr305:$jsr305_version"
66
implementation "org.junit.jupiter:junit-jupiter-api:$junit5_version"
7-
testImplementation "io.rest-assured:rest-assured:$restassured_version"
7+
testImplementation "io.vertx:vertx-junit5:$vertx_version"
8+
testImplementation "io.vertx:vertx-web-client:$vertx_version"
89
testImplementation "org.assertj:assertj-core:$assertj_version"
910
}

0 commit comments

Comments
 (0)