@@ -171,7 +171,7 @@ public void invokeHandler_nullResponse_returnsFailure(final String requestDataPa
171171
172172 // verify that model validation occurred for CREATE/UPDATE/DELETE
173173 if (action == Action .CREATE || action == Action .UPDATE || action == Action .DELETE ) {
174- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
174+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
175175 }
176176
177177 verify (providerEventsLogger ).refreshClient ();
@@ -190,6 +190,36 @@ public void invokeHandler_nullResponse_returnsFailure(final String requestDataPa
190190 }
191191 }
192192
193+ @ Test
194+ public void invokeHandler_SchemaFailureOnNestedProperties () throws IOException {
195+ // use actual validator to verify behaviour
196+ final WrapperOverride wrapper = new WrapperOverride (providerLoggingCredentialsProvider , platformEventsLogger ,
197+ providerEventsLogger , providerMetricsPublisher , new Validator () {
198+ }, httpClient );
199+
200+ wrapper .setTransformResponse (resourceHandlerRequest );
201+
202+ try (final InputStream in = loadRequestStream ("create.request.with-extraneous-model-object.json" );
203+ final OutputStream out = new ByteArrayOutputStream ()) {
204+ final Context context = getLambdaContext ();
205+
206+ wrapper .handleRequest (in , out , context );
207+ // validation failure metric should be published but no others
208+ verify (providerMetricsPublisher ).publishExceptionMetric (any (Instant .class ), eq (Action .CREATE ), any (Exception .class ),
209+ any (HandlerErrorCode .class ));
210+
211+ // all metrics should be published, even for a single invocation
212+ verify (providerMetricsPublisher ).publishInvocationMetric (any (Instant .class ), eq (Action .CREATE ));
213+
214+ // verify initialiseRuntime was called and initialised dependencies
215+ verifyInitialiseRuntime ();
216+
217+ // verify output response
218+ verifyHandlerResponse (out , ProgressEvent .<TestModel , TestContext >builder ().errorCode (HandlerErrorCode .InvalidRequest )
219+ .status (OperationStatus .FAILED ).message ("Resource properties validation failed with invalid configuration" ).build ());
220+ }
221+ }
222+
193223 @ Test
194224 public void invokeHandlerForCreate_without_customer_loggingCredentials () throws IOException {
195225 invokeHandler_without_customerLoggingCredentials ("create.request-without-logging-credentials.json" , Action .CREATE );
@@ -224,7 +254,7 @@ private void invokeHandler_without_customerLoggingCredentials(final String reque
224254
225255 // verify that model validation occurred for CREATE/UPDATE/DELETE
226256 if (action == Action .CREATE || action == Action .UPDATE || action == Action .DELETE ) {
227- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
257+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
228258 }
229259
230260 verifyNoMoreInteractions (providerEventsLogger );
@@ -259,7 +289,7 @@ public void invokeHandler_handlerFailed_returnsFailure(final String requestDataP
259289
260290 // verify that model validation occurred for CREATE/UPDATE/DELETE
261291 if (action == Action .CREATE || action == Action .UPDATE || action == Action .DELETE ) {
262- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
292+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
263293 }
264294
265295 // verify output response
@@ -318,7 +348,7 @@ public void invokeHandler_CompleteSynchronously_returnsSuccess(final String requ
318348
319349 // verify that model validation occurred for CREATE/UPDATE/DELETE
320350 if (action == Action .CREATE || action == Action .UPDATE || action == Action .DELETE ) {
321- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
351+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
322352 }
323353
324354 // verify output response
@@ -467,7 +497,7 @@ public void reInvokeHandler_InProgress_returnsInProgress(final String requestDat
467497
468498 // verify that model validation occurred for CREATE/UPDATE/DELETE
469499 if (action == Action .CREATE || action == Action .UPDATE || action == Action .DELETE ) {
470- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
500+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
471501 }
472502
473503 // verify output response
@@ -481,6 +511,7 @@ public void reInvokeHandler_InProgress_returnsInProgress(final String requestDat
481511 public void invokeHandler_SchemaValidationFailure (final String requestDataPath , final String actionAsString )
482512 throws IOException {
483513 final Action action = Action .valueOf (actionAsString );
514+
484515 doThrow (ValidationException .class ).when (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
485516
486517 wrapper .setTransformResponse (resourceHandlerRequest );
@@ -502,7 +533,7 @@ public void invokeHandler_SchemaValidationFailure(final String requestDataPath,
502533
503534 // verify that model validation occurred for CREATE/UPDATE/DELETE
504535 if (action == Action .CREATE || action == Action .UPDATE || action == Action .DELETE ) {
505- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
536+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
506537 }
507538
508539 // verify output response
@@ -548,7 +579,6 @@ providerEventsLogger, providerMetricsPublisher, new Validator() {
548579 final Context context = getLambdaContext ();
549580
550581 wrapper .handleRequest (in , out , context );
551-
552582 // validation failure metric should be published but no others
553583 verify (providerMetricsPublisher , times (1 )).publishExceptionMetric (any (Instant .class ), eq (Action .CREATE ),
554584 any (Exception .class ), any (HandlerErrorCode .class ));
@@ -711,7 +741,7 @@ public void invokeHandler_throwsAmazonServiceException_returnsServiceException()
711741 any (AmazonServiceException .class ), any (HandlerErrorCode .class ));
712742
713743 // verify that model validation occurred for CREATE/UPDATE/DELETE
714- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
744+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
715745
716746 // verify output response
717747 verifyHandlerResponse (out ,
@@ -728,7 +758,7 @@ public void invokeHandler_throwsSDK2ServiceException_returnsServiceException() t
728758 wrapper .setTransformResponse (resourceHandlerRequest );
729759
730760 try (final InputStream in = loadRequestStream ("create.request.json" );
731- final OutputStream out = new ByteArrayOutputStream ()) {
761+ final OutputStream out = new ByteArrayOutputStream ()) {
732762 final Context context = getLambdaContext ();
733763
734764 wrapper .handleRequest (in , out , context );
@@ -745,7 +775,7 @@ public void invokeHandler_throwsSDK2ServiceException_returnsServiceException() t
745775 any (CloudWatchLogsException .class ), any (HandlerErrorCode .class ));
746776
747777 // verify that model validation occurred for CREATE/UPDATE/DELETE
748- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
778+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
749779
750780 // verify output response
751781 verifyHandlerResponse (out ,
@@ -780,7 +810,7 @@ public void invokeHandler_throwsResourceAlreadyExistsException_returnsAlreadyExi
780810 any (ResourceAlreadyExistsException .class ), any (HandlerErrorCode .class ));
781811
782812 // verify that model validation occurred for CREATE/UPDATE/DELETE
783- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
813+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
784814
785815 // verify output response
786816 verifyHandlerResponse (out ,
@@ -815,7 +845,7 @@ public void invokeHandler_throwsResourceNotFoundException_returnsNotFound() thro
815845 any (ResourceNotFoundException .class ), any (HandlerErrorCode .class ));
816846
817847 // verify that model validation occurred for CREATE/UPDATE/DELETE
818- verify (validator , times ( 1 ) ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
848+ verify (validator ).validateObject (any (JSONObject .class ), any (JSONObject .class ));
819849
820850 // verify output response
821851 verifyHandlerResponse (out ,
0 commit comments