citrusframework / citrus

Framework for automated integration tests with focus on messaging integration
https://citrusframework.org
Apache License 2.0
445 stars 135 forks source link

[OpenAPI] NPE when validating nullable JSON properties #1173

Open ueberfuhr opened 3 weeks ago

ueberfuhr commented 3 weeks ago

Citrus Version 4.2.1

Expected behavior When receiving a response with nullable JSON properties, they should only be validated if they have a value.

Actual behavior Instead, we get an NPE.

Caused by: java.lang.NullPointerException: Cannot invoke "String.length()" because "text" is null
    at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1474)
    at java.base/java.text.DateFormat.parse(DateFormat.java:397)
    at org.citrusframework.validation.matcher.core.DatePatternValidationMatcher.validate(DatePatternValidationMatcher.java:46)
    at org.citrusframework.validation.matcher.ValidationMatcherUtils.resolveValidationMatcher(ValidationMatcherUtils.java:75)
    at org.citrusframework.validation.json.JsonElementValidator.validate(JsonElementValidator.java:53)
    at org.citrusframework.validation.json.JsonElementValidator.validateJSONObject(JsonElementValidator.java:85)
    at org.citrusframework.validation.json.JsonElementValidator.validate(JsonElementValidator.java:55)
    at org.citrusframework.validation.json.JsonTextMessageValidator.validateMessage(JsonTextMessageValidator.java:75)
    at org.citrusframework.validation.json.JsonTextMessageValidator.validateMessage(JsonTextMessageValidator.java:43)
    at org.citrusframework.validation.AbstractMessageValidator.validateMessage(AbstractMessageValidator.java:41)
    at org.citrusframework.actions.ReceiveMessageAction.validateMessage(ReceiveMessageAction.java:263)
    at org.citrusframework.actions.ReceiveMessageAction.doExecute(ReceiveMessageAction.java:167)
    at org.citrusframework.actions.AbstractTestAction.execute(AbstractTestAction.java:59)
    at org.citrusframework.DefaultTestCase.executeAction(DefaultTestCase.java:190)
    ... 8 more

Test case sample This is the return type in OpenAPI:

components:
  schemas:
    Todo:
      type: object
      required:
        - title
      properties:
        id:
          format: int64
          type: integer
          readOnly: true
        title:
          minLength: 3
          type: string
        completed:
          type: boolean
        due_date:
          format: date
          type: string
          example: 2022-03-10

and the corresponding JSON response:

{
  "id": 1,
  "title": "rGH",
  "completed": false,
  "due_date": null
}
ueberfuhr commented 3 weeks ago

The only way to avoid the exception is to disable validation for optional fields:

OpenApiSpecification apiSpecification = OpenApiSpecification.from(
    Resources.create("classpath:META-INF/resources/openapi.yml")
);
apiSpecification.setValidateOptionalFields(false);

But this will disable the complete validation. It should be possible to validate those fields if they are not null. So we need a possibility to influence the control message, which requires an extension to the validation matches. This could be one of the following ideas:

ueberfuhr commented 3 weeks ago

Another unpleasant thing is that, in the case of disabled validation of optional fields, the control message only contains the required fields, which will fail if the JSON validator is in strict mode. I guess, it should not fail, if we disable validation of optional fields, because they are declared in the OpenAPI.

christophd commented 2 weeks ago

Agreed, we need to make the null value validation more robust. Thank you for reporting this! In case you have some time to implement your ideas contributions are very welcome! Many thanks!