0

I've these two methods from my MetadataManagement class which I'd like to unit test:

@Override
protected void doPut(final HttpServletRequest request, final HttpServletResponse response,
    final MetadataResource resource)
    throws IOException {
  ServiceCommon.checkRole(getSubject(request));

  if (resource.getType() != Type.CONTAINER) {
    final String err = "Request not allowed for " + request.getURI();
    throw new ServiceApiException(ServiceApiError.METHOD_NOT_ALLOWED, err);
  }

  final String name = getContainerName(resource);

  final ServiceApiMetadata config = getConfig(request, PATH);

  final StorageLocation storageLocation = getStorageLocation(conf.getStorageLocation());

  if (config.getNotifications() != null) {
    checkMethodSupported(id);
    checkService(id);
  }
}

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 I understand it I can not directly call getConfig in my test because the method is private. I believe using reflection is an option but is not advised. Based on that, any test of getConfig should be done through doPut.

What I'm most interested in checking is if getConfig.isGoldStar is true, the origSchema pattern updates to ^[0-9A-Za-z]*$ and if it is false it remains at ^[0-9A-Za-z-._]*$.

To call doPut in my test I will need HttpServletRequest, HttpServletResponse and MetadataResource objects. I'm not sure how I generate these. HttpServletRequest and HttpServletResponse are from javax.servlet.ServletRequest and MetadataResource comes from within my project. It takes HttpServletRequest and an enum as parameters.

How do I do this test? I think I should be OK once I can call the doPut method but I'm struggling to do that.

runnerpaul
  • 5,942
  • 8
  • 49
  • 118
  • 1
    The spring-test library has `MockHttpServlet*` implementations that can be passed in for such use cases. – BeUndead Jan 23 '20 at 17:13
  • You should not test your private methods. It breaks the encapsulation. If there is a significant piece of logic in your private method - you probably have to extract it to a separate public class and test that class instead. – Ziumin Jan 23 '20 at 17:19
  • Thanks @user2478398. Looking at that now. @Ziumin what about testing the `getConfig` response? It should have the pattern value I want to test. – runnerpaul Jan 23 '20 at 17:22
  • If that's acceptable to you, you could declare the method as package private, so tests in the same package can access it. (less clean than extracting classes, but much less change is required.) – Daniele Jan 23 '20 at 22:01
  • See also https://stackoverflow.com/questions/34571/how-do-i-test-a-private-function-or-a-class-that-has-private-methods-fields-or ( that this question very much duplicates) – Daniele Jan 23 '20 at 22:02

0 Answers0