I'm trying to test this method:
private ServiceApiMetadata getConfig(final HttpServletRequest request, final String path)
throws IOException {
final Schema schema;
try (final InputStream inStream = this.getClass().getResourceAsStream(path)) {
final JSONObject origSchema = new JSONObject(new JSONTokener(inStream));
if (isGoldStar()) {
origSchema.getJSONObject("properties")
.getJSONObject("notifications")
.getJSONObject("properties")
.getJSONObject("topic")
.put("pattern", "^[0-9A-Za-z-.]*$");
}
schema = SchemaLoader.load(origSchema);
}
final ServiceApiMetadata config;
try (final BufferedReader reader = request.getReader()) {
final JSONObject json = new JSONObject(new JSONTokener(reader));
schema.validate(json);
config = ServiceApiMetadata.read(json);
} catch (final ValidationException e) {
_logger.debug(e.getMessage());
if (e.getLocation().contains("#/properties/notifications")) {
throw new ServiceApiException(ServiceApiError.MALFORMED_NOTIFICATIONS_ERROR,
ServiceApiErrorMessage.MALFORMED_JSON);
} else {
throw new ServiceApiException(ServiceApiError.MALFORMED_JSON);
}
} catch (final JSONException e) {
_logger.debug(e.getMessage());
throw new ServiceApiException(ServiceApiError.MALFORMED_JSON);
}
return config;
}
As it's private I created the following method in my class:
@TestOnly
protected void runGetConfig(final HttpServletRequest request, final String schemaPath) throws IOException {
final ServiceApiMetadata conf = getConfig(request, schemaPath);
}
When I run my test getConfig()
throws an exception. The problem is that when line final JSONObject json = new JSONObject(new JSONTokener(reader));
I get this exception:
HttpException(400,{"status_code":400,"error_code":"MalformedJson","uri":"uri","message":"MalformedJson"},null)
I also see this error in my log:
at 0 [character 1 line 1]
For the HttpServletRequest I'm using org.springframework.mock.web.MockHttpServletRequest.MockHttpServletRequest()
as follows:
final MockHttpServletRequest request = new MockHttpServletRequest();
Is it possible this is creating an incorrect reader
which in turn means the JSONObject
is incorrect and if so how do I resolve this?
Additional info
I added a body to the MockHttpServletRequest
but the issue is still the same. I added some logging as can be seen below:
final JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream));
_logger.info("rawSchema: " + rawSchema);
if (isPulsar()) {
rawSchema.getJSONObject("properties")
.getJSONObject("notifications")
.getJSONObject("properties")
.getJSONObject("topic")
.put("pattern", "^[0-9A-Za-z-._:/]*$");
}
schema = SchemaLoader.load(rawSchema);
}
final ServiceApiContainerMetadata conf;
try (final BufferedReader reader = request.getReader()) {
_logger.info("reader: " + reader);
_logger.info("JSONTokener(reader): " + new JSONTokener(reader.readLine()));
final JSONObject json = new JSONObject(new JSONTokener(reader.readLine()));
It shows me this in the output:
rawSchema: {VALID JSON STRUCTURE. IT'S TOO BIG TO INCLUDE IN THIS QUESTION}
reader: java.io.BufferedReader@4c4d27c8
JSONTokener(reader): at 0 [character 1 line 1]
Info on MockHttpServletRequest
The body of my MockHttpServletRequest
contains the Lorem ipsum text. If I add the following code below my BufferedReader that text is printed to console. That same text is also used in ``final JSONObject json = new JSONObject(new JSONTokener(reader.readLine()));so the malformed JSON error in my
HttpException` is no surprise.
while ((strCurrentLine = reader.readLine()) != null) {
_logger.info("reader: " + strCurrentLine);
}
Could this be a bug in my code? Should final JSONObject json = new JSONObject(new JSONTokener(reader.readLine()));
in fact be final JSONObject json = new JSONObject(schema);
? If I try that I can get see the code now reaches schema.validate(json);
but there are 12 schema violations found
. I can't see what these are though. Another thought is should the body be JSON?
I updated the body to JSON which resulted in 2 validation errors. One was that service_id
was missing and testkey
was present so I resolved that and my method no longer throws an exception when I use final JSONObject json = new JSONObject(new JSONTokener(reader));
.
To resolve this I added a notifications
key to my body JSON. This allowed final JSONObject json = new JSONObject(new JSONTokener(reader.readLine())); to work
.