Auto‑Generating Java API Test Code from Swagger JSON
This article explains how to parse a Swagger JSON document and automatically generate maintainable Java test code for each API endpoint, detailing the handling of GET query parameters, POST form‑data, RESTful path variables, and header conventions.
Refactoring the request generation logic
The original monolithic magic() method was decomposed into a set of small, focused methods. This improves readability, testability, and future maintenance.
Generating test code from Swagger
A Swagger contract is used as the single source of truth: GET endpoints use query parameters, POST endpoints use form‑data (except file uploads), and shared parameters are placed in headers. The Swagger JSON is parsed to build Request objects, which are then converted into ready‑to‑run Java test methods.
package com.fission.source.until;
import com.fission.source.profile.Constant;
import com.fission.source.source.SourceCode;
import lombok.Data;
import net.sf.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Data
public class Request extends SourceCode {
private String url; // request URL
private String type; // GET / POST
private String apiName; // method name
private String desc; // description
List<String> restfulArgs = new ArrayList<>(); // {id} placeholders
JSONObject args = new JSONObject(); // query parameters
JSONObject params = new JSONObject(); // form‑data parameters
StringBuffer stringBuffer = new StringBuffer(); // method signature builder
StringBuffer code = new StringBuffer(); // generated method body
boolean postNoParams = false; // true when POST has no body
/** Append JSON argument creation code */
private void spliceArgs(int i) {
String type = i == 1 ? "params" : "args";
code.append(LINE + TAB + TAB + "JSONObject " + type + " = new JSONObject();");
Set keySet = i == 0 ? args.keySet() : params.keySet();
keySet.forEach(key -> {
collectArgs(key.toString(), (i == 0 ? args : params).getString(key.toString()));
code.append(LINE + TAB + TAB + type + ".put(\"" + key + "\", " + key + ");");
});
}
/** Build method‑parameter fragment based on Swagger type */
private void collectArgs(String key, String value) {
if (value.equals("string")) stringBuffer.append("String " + key + ",");
if (value.equals("integer")) stringBuffer.append("int " + key + ",");
}
/** Extract RESTful placeholders from the URL */
private void collectRestfulArgs() {
if (url.contains("{")) {
List<String> placeholders = regexAll(url, "\\{[^}]+\\}");
placeholders.forEach(p -> restfulArgs.add(p.replace("{", "").replace("}", "")));
}
}
/** Build the URL string, inserting placeholders as method parameters */
private String spliceUrl() {
collectRestfulArgs();
url = url.contains("{") ? url : url + "\"";
url = "\"" + url.replace("}/{", "+OR+").replace("{", "\"+").replace("}", "") + "\"";
return TAB + TAB + "String url = HOST + " + url + ";";
}
/** Generate GET request code */
private void spliceGet() {
if (!args.isEmpty()) {
spliceArgs(0);
code.append(LINE + TAB + TAB + "HttpGet httpGet = getHttpGet(url, args);");
} else {
code.append(LINE + TAB + TAB + "HttpGet httpGet = getHttpGet(url);");
}
code.append(LINE + TAB + TAB + "JSONObject response = getHttpResponse(httpGet);");
}
/** Generate POST request code */
private void splicePost() {
if (!args.isEmpty()) spliceArgs(0);
if (!params.isEmpty()) spliceArgs(1);
if (args.isEmpty()) {
if (!params.isEmpty()) {
code.append(LINE + TAB + TAB + "HttpPost httpPost = getHttpPost(url, params);");
} else {
code.append(LINE + TAB + TAB + "HttpPost httpPost = getHttpPost(url);");
}
} else {
if (!params.isEmpty()) {
code.append(LINE + TAB + TAB + "HttpPost httpPost = getHttpPost(url, args, params);");
} else {
postNoParams = true;
}
}
code.append(LINE + TAB + TAB + "JSONObject response = getHttpResponse(httpPost);");
}
/** Finalise method body */
private String spliceEnd() {
restfulArgs.forEach(a -> stringBuffer.append("int " + a + ","));
code.append(LINE + TAB + TAB + "output(response);");
code.append(LINE + TAB + TAB + "return response;");
code.append(LINE + TAB + "}");
return code.toString()
.replace("() {", "(" + stringBuffer.toString() + ") {")
.replace(",)", ")");
}
/** Convert the request definition into a Java method */
public String magic() {
code.append(TAB + "/**
* " + desc + "
*/" + LINE);
code.append(TAB + "public JSONObject " + apiName + "() {" + LINE);
String urlLine = spliceUrl();
code.append(urlLine);
if (type.equals(REQUEST_TYPE_GET)) spliceGet();
if (type.equals(REQUEST_TYPE_POST)) splicePost();
String finalCode = spliceEnd();
if (postNoParams) {
finalCode = finalCode.replace(urlLine, urlLine.replace(";", "") + " + changeJsonToArguments(args)");
}
output(finalCode);
return finalCode;
}
}Swagger parser
The Swagger class reads a Swagger JSON document, extracts module names, URLs, and parameter definitions, and creates a list of Request objects for a selected module.
package com.fission.source.until;
import com.fission.source.source.ApiLibrary;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class Swagger extends ApiLibrary {
String key; // prefix before the URL path
String swaggerPath; // location of swagger.json
String name; // module name selected by the user
String url; // optional single endpoint URL
List<String> names = new ArrayList<>(); // all module names
List<String> urls = new ArrayList<>(); // all endpoint paths
JSONObject swagger = new JSONObject(); // whole swagger document
JSONObject paths = new JSONObject(); // "paths" node
Request request = new Request();
List<Request> requests = new ArrayList<>();
public static void main(String[] args) {
String surl = "http://10.10.32.158:6005/swagger.json";
String sname = "Guild Initial Module";
Swagger swagger = new Swagger(surl, sname);
swagger.requests.forEach(r -> r.magic());
testOver();
}
public Swagger(String swaggerPath, String name) {
this.swaggerPath = swaggerPath;
this.name = name;
build();
}
/** Initialise parsing and object creation */
public void build() {
swagger = getHttpResponse(getHttpGet(swaggerPath));
getKey();
getNames();
getPaths();
getUrls();
getRequests();
}
private void getKey() {
key = regexAll(swaggerPath, "/((?!/).)*/swagger.json").get(0)
.replace(OR, "").replace("swagger.json", "");
if (key.contains(":")) key = "";
}
private void getNames() {
JSONArray tags = swagger.getJSONArray("tags");
tags.forEach(t -> names.add(((JSONObject) t).getString("name")));
}
private void getPaths() {
paths = swagger.getJSONObject("paths");
}
private void getUrls() {
Set keySet = paths.keySet();
keySet.forEach(k -> urls.add(k.toString()));
}
private void getRequests() {
urls.forEach(u -> {
Request r = getRequest(u);
if (r != null) requests.add(r);
});
}
/** Create a Request object for a specific endpoint */
private Request getRequest(String url) {
Request req = new Request();
req.setUrl((OR + key + url).replace("//", "/"));
JSONObject node = paths.getJSONObject(url);
JSONObject operation = null;
if (node.containsKey("get")) {
req.setType(REQUEST_TYPE_GET);
operation = node.getJSONObject("get");
} else if (node.containsKey("post")) {
req.setType(REQUEST_TYPE_POST);
operation = node.getJSONObject("post");
}
if (operation == null) return null;
if (!operation.getString("tags").contains(name)) return null;
req.setApiName(operation.getString("operationId"));
req.setDesc(operation.getString("summary"));
JSONArray parameters = operation.getJSONArray("parameters");
JSONObject query = new JSONObject();
JSONObject form = new JSONObject();
parameters.forEach(p -> {
JSONObject param = (JSONObject) p;
String in = param.getString("in");
if (in.equals("query") && param.getBoolean("required")) {
query.put(param.getString("name"), param.getString("type"));
} else if (in.equals("formData") && param.getBoolean("required")) {
form.put(param.getString("name"), param.getString("type"));
}
});
req.setArgs(query);
req.setParams(form);
return req;
}
}Key implementation details
RESTful placeholders such as {id} are detected with a regular expression and turned into method parameters.
Swagger parameters entries are classified into query arguments ( args) and form‑data arguments ( params) based on the in field.
Parameter types are mapped to Java types: string → String, integer → int. The generated method signature is built dynamically.
Header handling and response output ( output(response)) are inserted automatically.
If a POST endpoint has no form‑data, the query string is appended directly to the URL (controlled by postNoParams).
Usage
Running the main method of Swagger reads the Swagger document, creates a Request for each endpoint in the selected module, and calls magic(). The result is a Java method per API that can be used directly in automated tests, eliminating repetitive hand‑coding.
Consistent Swagger contracts are required; mismatches between the contract and the actual service will produce incorrect generated code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
