Skip to content

Commit c789467

Browse files
committed
test: Add SpecFixtures helper to derive multiple specs from one fixture
1 parent e1a5790 commit c789467

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package com.retailsvc.http.support;
2+
3+
import com.google.gson.Gson;
4+
import com.retailsvc.http.spec.Spec;
5+
import java.io.IOException;
6+
import java.io.InputStream;
7+
import java.io.InputStreamReader;
8+
import java.io.Reader;
9+
import java.io.UncheckedIOException;
10+
import java.nio.charset.StandardCharsets;
11+
import java.util.ArrayList;
12+
import java.util.LinkedHashMap;
13+
import java.util.List;
14+
import java.util.Map;
15+
16+
/**
17+
* Test-only helper: loads {@code /openapi.json} from the classpath, deep-clones the parsed map, and
18+
* re-points {@code servers[0].url} so callers can derive multiple {@link Spec} instances from a
19+
* single fixture file.
20+
*/
21+
public final class SpecFixtures {
22+
23+
private SpecFixtures() {}
24+
25+
/** Loads the test spec and rewrites {@code servers[0].url} to {@code newServerUrl}. */
26+
public static Spec specAt(String newServerUrl) {
27+
Map<String, Object> raw = readBaseSpec();
28+
@SuppressWarnings("unchecked")
29+
List<Map<String, Object>> servers = (List<Map<String, Object>>) raw.get("servers");
30+
if (servers == null || servers.isEmpty()) {
31+
throw new IllegalStateException("test spec has no servers entry");
32+
}
33+
servers.get(0).put("url", newServerUrl);
34+
return Spec.from(raw);
35+
}
36+
37+
private static Map<String, Object> readBaseSpec() {
38+
try (InputStream in = SpecFixtures.class.getResourceAsStream("/openapi.json")) {
39+
if (in == null) {
40+
throw new IllegalStateException("/openapi.json not found on test classpath");
41+
}
42+
return parse(in);
43+
} catch (IOException e) {
44+
throw new UncheckedIOException(e);
45+
}
46+
}
47+
48+
@SuppressWarnings("unchecked")
49+
private static Map<String, Object> parse(InputStream in) {
50+
Gson gson = new Gson();
51+
try (Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
52+
Map<String, Object> root = gson.fromJson(reader, Map.class);
53+
return deepClone(root);
54+
} catch (IOException e) {
55+
throw new UncheckedIOException(e);
56+
}
57+
}
58+
59+
@SuppressWarnings("unchecked")
60+
private static Map<String, Object> deepClone(Map<String, Object> in) {
61+
Map<String, Object> out = new LinkedHashMap<>(in.size());
62+
for (var e : in.entrySet()) {
63+
out.put(e.getKey(), cloneValue(e.getValue()));
64+
}
65+
return out;
66+
}
67+
68+
@SuppressWarnings("unchecked")
69+
private static Object cloneValue(Object v) {
70+
if (v instanceof Map<?, ?> m) {
71+
return deepClone((Map<String, Object>) m);
72+
}
73+
if (v instanceof List<?> l) {
74+
List<Object> out = new ArrayList<>(l.size());
75+
for (Object item : l) {
76+
out.add(cloneValue(item));
77+
}
78+
return out;
79+
}
80+
return v;
81+
}
82+
}

0 commit comments

Comments
 (0)