Skip to content

Commit 6ef0d94

Browse files
committed
test: Cover multi-spec namespacing, conflicts, and mixed builder forms
1 parent cf8152d commit 6ef0d94

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

src/test/java/com/retailsvc/http/MultiSpecServerTest.java

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static java.net.HttpURLConnection.HTTP_OK;
44
import static org.assertj.core.api.Assertions.assertThat;
5+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
56

67
import com.retailsvc.http.spec.Spec;
78
import com.retailsvc.http.support.SpecFixtures;
@@ -11,6 +12,8 @@
1112
import java.net.http.HttpResponse;
1213
import java.util.LinkedHashMap;
1314
import java.util.Map;
15+
import java.util.concurrent.atomic.AtomicInteger;
16+
import org.junit.jupiter.api.Assumptions;
1417
import org.junit.jupiter.api.Test;
1518

1619
class MultiSpecServerTest {
@@ -41,6 +44,100 @@ void servesTwoBindingsOnDistinctBasePaths() throws Exception {
4144
}
4245
}
4346

47+
@Test
48+
void identicalOperationIdsAcrossBindingsDispatchIndependently() throws Exception {
49+
Spec v1 = SpecFixtures.specAt("http://localhost/api/v1");
50+
Spec v2 = SpecFixtures.specAt("http://localhost/api/v2");
51+
52+
AtomicInteger v1Hits = new AtomicInteger();
53+
AtomicInteger v2Hits = new AtomicInteger();
54+
55+
Map<String, RequestHandler> v1Handlers =
56+
handlersFor(
57+
v1,
58+
req -> {
59+
v1Hits.incrementAndGet();
60+
return Response.ok(Map.of("v", 1));
61+
});
62+
Map<String, RequestHandler> v2Handlers =
63+
handlersFor(
64+
v2,
65+
req -> {
66+
v2Hits.incrementAndGet();
67+
return Response.ok(Map.of("v", 2));
68+
});
69+
70+
try (OpenApiServer server =
71+
OpenApiServer.builder()
72+
.port(0)
73+
.addSpec(v1, v1Handlers)
74+
.addSpec(v2, v2Handlers)
75+
.useExternalAuthentication()
76+
.build()) {
77+
78+
int port = server.listenPort();
79+
get("http://localhost:" + port + "/api/v1/data");
80+
get("http://localhost:" + port + "/api/v2/data");
81+
82+
assertThat(v1Hits.get()).isEqualTo(1);
83+
assertThat(v2Hits.get()).isEqualTo(1);
84+
}
85+
}
86+
87+
@Test
88+
void rejectsTwoBindingsWithSameBasePath() {
89+
Spec a = SpecFixtures.specAt("http://localhost/api/v1");
90+
Spec b = SpecFixtures.specAt("http://localhost/api/v1");
91+
Map<String, RequestHandler> handlersA = handlersFor(a, req -> Response.ok(Map.of()));
92+
Map<String, RequestHandler> handlersB = handlersFor(b, req -> Response.ok(Map.of()));
93+
94+
assertThatThrownBy(
95+
() ->
96+
OpenApiServer.builder()
97+
.port(0)
98+
.addSpec(a, handlersA)
99+
.addSpec(b, handlersB)
100+
.useExternalAuthentication()
101+
.build())
102+
.isInstanceOf(IllegalStateException.class)
103+
.hasMessageContaining("duplicate basePath")
104+
.hasMessageContaining("/api/v1");
105+
}
106+
107+
@Test
108+
void missingValidatorOnOneBindingFailsIndependently() {
109+
Spec v1 = SpecFixtures.specAt("http://localhost/api/v1");
110+
Assumptions.assumeTrue(
111+
!v1.securitySchemes().isEmpty(), "test spec has no security schemes to exercise");
112+
113+
Map<String, RequestHandler> handlers = handlersFor(v1, req -> Response.ok(Map.of()));
114+
115+
assertThatThrownBy(
116+
() -> OpenApiServer.builder().port(0).addSpec(v1, handlers, Map.of()).build())
117+
.isInstanceOf(IllegalStateException.class)
118+
.hasMessageContaining("no SchemeValidator registered for security scheme");
119+
}
120+
121+
@Test
122+
void rejectsMixingLegacySpecMethodsWithAddSpec() {
123+
Spec a = SpecFixtures.specAt("http://localhost/api/v1");
124+
Spec b = SpecFixtures.specAt("http://localhost/api/v2");
125+
Map<String, RequestHandler> handlersA = handlersFor(a, req -> Response.ok(Map.of()));
126+
Map<String, RequestHandler> handlersB = handlersFor(b, req -> Response.ok(Map.of()));
127+
128+
assertThatThrownBy(
129+
() ->
130+
OpenApiServer.builder()
131+
.port(0)
132+
.spec(a)
133+
.handlers(handlersA)
134+
.addSpec(b, handlersB)
135+
.useExternalAuthentication()
136+
.build())
137+
.isInstanceOf(IllegalStateException.class)
138+
.hasMessageContaining("use either spec()/handler()/securityValidator() or addSpec()");
139+
}
140+
44141
private static Map<String, RequestHandler> handlersFor(Spec spec, RequestHandler shared) {
45142
Map<String, RequestHandler> out = new LinkedHashMap<>();
46143
spec.operations().forEach(op -> out.put(op.operationId(), shared));

0 commit comments

Comments
 (0)