From dfbc9bc7cbdc2b97d5daefc821e0049a911f2650 Mon Sep 17 00:00:00 2001 From: Robert Baillie Date: Thu, 2 Dec 2021 08:51:03 +0000 Subject: [PATCH] Improving test coverage and fixing bugs --- .../classes/exceptions/ortoo_Exception.cls | 5 +- .../exceptions/tests/ExceptionsTest.cls | 31 +++++ .../exceptions/tests/ortoo_ExceptionTest.cls | 98 ++++++++++++++- .../tests/MessageRendererEngineTest.cls | 117 ++++++++++-------- ...w-fails.sh => run-tests-and-show-fails.sh} | 0 5 files changed, 193 insertions(+), 58 deletions(-) rename scripts/helpers/{test-and-show-fails.sh => run-tests-and-show-fails.sh} (100%) diff --git a/framework/default/ortoo-core/default/classes/exceptions/ortoo_Exception.cls b/framework/default/ortoo-core/default/classes/exceptions/ortoo_Exception.cls index f12e72b72b8..8d67e5d33b7 100644 --- a/framework/default/ortoo-core/default/classes/exceptions/ortoo_Exception.cls +++ b/framework/default/ortoo-core/default/classes/exceptions/ortoo_Exception.cls @@ -164,7 +164,10 @@ public virtual class ortoo_Exception extends Exception implements IRenderableMes Set objectContexts = new Set(); for ( MessageDetail thisMessageDetail : messageDetails ) { - objectContexts.add( thisMessageDetail.getObjectContext() ); + if ( thisMessageDetail.getObjectContext() != null ) + { + objectContexts.add( thisMessageDetail.getObjectContext() ); + } } List returnList = new List( objectContexts ); diff --git a/framework/default/ortoo-core/default/classes/exceptions/tests/ExceptionsTest.cls b/framework/default/ortoo-core/default/classes/exceptions/tests/ExceptionsTest.cls index c06e03ab1a9..aef5c09aeee 100644 --- a/framework/default/ortoo-core/default/classes/exceptions/tests/ExceptionsTest.cls +++ b/framework/default/ortoo-core/default/classes/exceptions/tests/ExceptionsTest.cls @@ -45,4 +45,35 @@ private without sharing class ExceptionsTest System.assertEquals( 'CONF-123', e.getErrorCode(), 'ConfigurationException.setErrorCode, when called, will add a prefix to the code' ); } + + @isTest + private static void validationExceptionSetErrorCode_whenCalled_willNotAddAPrefixToTheCode() // NOPMD: Test method name format + { + Exceptions.ValidationException e = new Exceptions.ValidationException( new List() ); + e.setErrorCode( '123' ); + + System.assertEquals( '123', e.getErrorCode(), 'ValidationException.setErrorCode, when called, will NOT add a prefix to the code' ); + } + + @isTest + private static void validationException_whenConstructed_willSetTheMessage() // NOPMD: Test method name format + { + Exceptions.ValidationException e = new Exceptions.ValidationException( new List() ); + + System.assertEquals( Label.ortoo_core_validation_errors_occurred, e.getMessage(), 'ValidationException, when constructed, will set the message' ); + } + + @isTest + private static void validationException_whenConstructed_willSetTheMessageDetails() // NOPMD: Test method name format + { + List messageDetails = new List + { + new MessageDetail( 'content1' ), + new MessageDetail( 'content2' ) + }; + + Exceptions.ValidationException e = new Exceptions.ValidationException( messageDetails ); + + System.assertEquals( messageDetails, e.getMessageDetails(), 'ValidationException, when constructed, will set the message' ); + } } \ No newline at end of file diff --git a/framework/default/ortoo-core/default/classes/exceptions/tests/ortoo_ExceptionTest.cls b/framework/default/ortoo-core/default/classes/exceptions/tests/ortoo_ExceptionTest.cls index 42600d715dd..10a9246bf22 100644 --- a/framework/default/ortoo-core/default/classes/exceptions/tests/ortoo_ExceptionTest.cls +++ b/framework/default/ortoo-core/default/classes/exceptions/tests/ortoo_ExceptionTest.cls @@ -12,17 +12,29 @@ public with sharing class ortoo_ExceptionTest { Test.stopTest(); System.assertEquals( 'ErrorCode', e.getErrorCode(), 'setErrorCode, will set the error code that is returned by getErrorCode' ); + System.assertEquals( 'ErrorCode', e.getCode(), 'setErrorCode, will set the error code that is returned by getCode' ); } @isTest - private static void getStackTrace_whenCalled_willReturnAStackTraceObjectBasedOnWhenTheExceptionWasConstructed() // NOPMD: Test method name format + private static void getSeverity_willReturnError() // NOPMD: Test method name format + { + Test.startTest(); + ortoo_Exception e = new ortoo_Exception(); + MessageRendererEngine.Severity severity = e.getSeverity(); + Test.stopTest(); + + System.assertEquals( MessageRendererEngine.Severity.Error, severity, 'getSeverity, will return error' ); + } + + @isTest + private static void getStackTrace_whenCalled_willReturnAStackBasedOnConstruct() // NOPMD: Test method name format { Test.startTest(); ortoo_Exception e = new ortoo_Exception(); StackTrace trace = e.getStackTrace(); Test.stopTest(); - System.assertEquals( 'getStackTrace_whenCalled_willReturnAStackTraceObjectBasedOnWhenTheExceptionWasConstructed', trace.getInnermostMethodName(), 'getStackTrace, when called, will return a stack trace based on when the exception was constructed (method name)' ); + System.assertEquals( 'getStackTrace_whenCalled_willReturnAStackBasedOnConstruct', trace.getInnermostMethodName(), 'getStackTrace, when called, will return a stack trace based on when the exception was constructed (method name)' ); Amoss_Asserts.assertEndsWith( 'ortoo_ExceptionTest', trace.getInnermostClassName(), 'getStackTrace, when called, will return a stack trace based on when the exception was constructed (class name)' ); } @@ -65,7 +77,7 @@ public with sharing class ortoo_ExceptionTest { } @isTest - private static void getStackTraceString_whenConstructionIsInsideMultipleLayers_willReturnTheStackTrace() + private static void getStackTraceString_whenBuiltInsideLayers_willReturnTheStackTrace() { String stackTrace; Test.startTest(); @@ -82,7 +94,7 @@ public with sharing class ortoo_ExceptionTest { Amoss_Asserts.assertDoesNotContain( '', stackTrace, 'getStackTraceString, when construction is inside multiple layers of methods, will return the Stack Trace based on where the exception was raised - with each level (not the exception constructor)' ); Amoss_Asserts.assertContains( 'ortoo_ExceptionTest.throwAnOrtooExceptionInnerMethodCall', stackTrace, 'getStackTraceString, when construction is inside multiple layers of methods, will return the Stack Trace based on where the exception was raised - with each level (method 1)' ); Amoss_Asserts.assertContains( 'ortoo_ExceptionTest.throwAnOrtooException', stackTrace, 'getStackTraceString, when construction is inside multiple layers of methods, will return the Stack Trace based on where the exception was raised - with each level (method 2)' ); - Amoss_Asserts.assertContains( 'ortoo_ExceptionTest.getStackTraceString_whenConstructionIsInsideMultipleLayers_willReturnTheStackTrace', stackTrace, 'getStackTraceString, when construction is inside multiple layers of methods, will return the Stack Trace based on where the exception was raised - with each level (method 3)' ); + Amoss_Asserts.assertContains( 'ortoo_ExceptionTest.getStackTraceString_whenBuiltInsideLayers_willReturnTheStackTrace', stackTrace, 'getStackTraceString, when construction is inside multiple layers of methods, will return the Stack Trace based on where the exception was raised - with each level (method 3)' ); } @isTest @@ -131,7 +143,7 @@ public with sharing class ortoo_ExceptionTest { } @isTest - private static void addContext_whenCalledInAnInnerClass_willAddItToTheExceptionWithStackInfo() // NOPMD: Test method name format + private static void addContext_whenCalledInInnerClass_willAddIncludeInStack() // NOPMD: Test method name format { ortoo_Exception e = new ortoo_Exception( 'message' ); @@ -249,6 +261,82 @@ public with sharing class ortoo_ExceptionTest { System.assertEquals( true, exceptionCaught, 'next, when there are no entries in the list, will throw a NoSuchElementException exception' ); } + @isTest + private static void getObjectContext_whenMessageDetailsAdded_willReturnTheSobjects() // NOPMD: Test method name format + { + ortoo_Exception exceptionUnderTest = new ortoo_Exception( 'message' ); + + List objectContexts = new List + { + new Contact( Id = TestIdUtils.generateId( Contact.sobjectType ) ), + new Contact( Id = TestIdUtils.generateId( Contact.sobjectType ) ), + new Contact( Id = TestIdUtils.generateId( Contact.sobjectType ) ) + }; + + Test.startTest(); + exceptionUnderTest.setMessageDetails( + new List + { + new MessageDetail( objectContexts[0], 'message1' ), + new MessageDetail( objectContexts[1], 'message2' ), + new MessageDetail( objectContexts[1], 'message3' ), + new MessageDetail( objectContexts[0], 'message4' ) + } + ); + List returnedObjectContexts = exceptionUnderTest.getObjectContexts(); + + Test.stopTest(); + + List expectedObjectContexts = new List{ objectContexts[0], objectContexts[1] }; + + System.assertEquals( expectedObjectContexts, returnedObjectContexts, 'getObjectContext, when some message details have been added, will return those objects' ); + } + + @isTest + private static void getObjectContext_whenNoMessageDetails_willReturnEmptySet() // NOPMD: Test method name format + { + ortoo_Exception exceptionUnderTest = new ortoo_Exception( 'message' ); + + Test.startTest(); + List returnedObjectContexts = exceptionUnderTest.getObjectContexts(); + Test.stopTest(); + + List expectedObjectContexts = new List(); + + System.assertEquals( expectedObjectContexts, returnedObjectContexts, 'getObjectContext, when no message details have been added, will return an empty set' ); + } + + @isTest + private static void getObjectContext_whenSomeDetailsHaveNull_willNotReturnTheNulls() // NOPMD: Test method name format + { + ortoo_Exception exceptionUnderTest = new ortoo_Exception( 'message' ); + + List objectContexts = new List + { + new Contact( Id = TestIdUtils.generateId( Contact.sobjectType ) ), + new Contact( Id = TestIdUtils.generateId( Contact.sobjectType ) ), + new Contact( Id = TestIdUtils.generateId( Contact.sobjectType ) ) + }; + + Test.startTest(); + exceptionUnderTest.setMessageDetails( + new List + { + new MessageDetail( objectContexts[0], 'message1' ), + new MessageDetail( objectContexts[2], 'message2' ), + new MessageDetail( 'message3' ), + new MessageDetail( objectContexts[0], 'message4' ) + } + ); + List returnedObjectContexts = exceptionUnderTest.getObjectContexts(); + + Test.stopTest(); + + List expectedObjectContexts = new List{ objectContexts[0], objectContexts[2] }; + + System.assertEquals( expectedObjectContexts, returnedObjectContexts, 'getObjectContext, when some message details have been added with null objects, will not return the nulls' ); + } + private class ContextAdder { private void addContext( ortoo_Exception e, String name, String value ) diff --git a/framework/default/ortoo-core/default/classes/message-renderer-engine/tests/MessageRendererEngineTest.cls b/framework/default/ortoo-core/default/classes/message-renderer-engine/tests/MessageRendererEngineTest.cls index f0cb6484446..4f2dd628439 100644 --- a/framework/default/ortoo-core/default/classes/message-renderer-engine/tests/MessageRendererEngineTest.cls +++ b/framework/default/ortoo-core/default/classes/message-renderer-engine/tests/MessageRendererEngineTest.cls @@ -45,6 +45,16 @@ private without sharing class MessageRendererEngineTest Amoss_Asserts.assertContains( 'render called before the message was set', exceptionMessage, 'render, when no message has been set, will throw an exception' ); } + @isTest + private static void getRenderer_whenTheRendererHasBeenSet_willReturnTheRenderer() // NOPMD: Test method name format + { + IMessageRenderer renderer = (IMessageRenderer)new Amoss_Instance( IMessageRenderer.class ).generateDouble(); + MessageRendererEngine engine = new MessageRendererEngine().setRenderer( renderer ); + + IMessageRenderer returnedRenderer = engine.getRenderer(); + System.assertEquals( renderer, returnedRenderer, 'getRenderer, when the renderer has been set, will return the renderer' ); + } + @isTest private static void render_whenCalledAgainstAConfiguredEngine_willCallRenderAgainstTheRenderer() // NOPMD: Test method name format { @@ -282,58 +292,6 @@ private without sharing class MessageRendererEngineTest System.assertEquals( 'Field detail content', detailError.getMessage(), 'SobjectMessageAdder, when render is called, will add messages of severity error to the related SObjects - setting the content a the detail error with a field' ); } - @isTest - private static void SobjectMessageAdder_whenRenderIsCalled_willNotAddInfoOrWarnAsErrors() // NOPMD: Test method name format - { - Amoss_Instance messageController = new Amoss_Instance( IRenderableMessageHeader.class ); - IRenderableMessageHeader message = (IRenderableMessageHeader)messageController.generateDouble(); - - Amoss_Instance fieldDetailController = new Amoss_Instance( IRenderableMessageDetail.class ); - IRenderableMessageDetail fieldDetail = (IRenderableMessageDetail)fieldDetailController.generateDouble(); - - List objectContexts = new List { - new Contact() - }; - - messageController - .when( 'getSeverity' ) - .returns( MessageRendererEngine.Severity.Info ) - .also() - .when( 'getObjectContexts' ) - .returns( objectContexts ) - .also() - .when( 'getMessage' ) - .returns( 'The header message' ) - .also() - .when( 'getMessageDetails' ) - .returns( new List{ fieldDetail } ); - - fieldDetailController - .when( 'getContent' ) - .returns( 'Field detail content' ) - .also() - .when( 'getObjectContext' ) - .returns( objectContexts[0] ) - .also() - .when( 'getFieldContext' ) - .returns( Contact.FirstName ) - .also() - .when( 'getSeverity' ) - .returns( MessageRendererEngine.Severity.Error ); - - MessageRendererEngine.SobjectMessageAdder renderer = new MessageRendererEngine.SobjectMessageAdder(); - - Test.startTest(); - Boolean messageRendered = renderer.render( message ); - Test.stopTest(); - - System.assert( ! messageRendered, 'SobjectMessageAdder, when render is called with an info or warning header message, will return false' ); - - List errors; - errors = objectContexts[0].getErrors(); - System.assertEquals( 0, errors.size(), 'SobjectMessageAdder, when render is called with an info or warning header message, will not add any messages to the sobjects' ); - } - @isTest private static void SobjectMessageAdder_whenRenderIsCalled_willNotAddInfoOrWarnDetailsAsErrors() // NOPMD: Test method name format { @@ -403,4 +361,59 @@ private without sharing class MessageRendererEngineTest System.assertEquals( 'The header message', errors[0].getMessage(), 'SobjectMessageAdder, when render is called with an error message that has no error details, will add the header message to the sobjects - checking the content' ); } + + @isTest + private static void SobjectMessageAdder_whenRenderIsCalled_willNotAddInfoOrWarnAsErrors() // NOPMD: Test method name format + { + Amoss_Instance messageController = new Amoss_Instance( IRenderableMessageHeader.class ); + IRenderableMessageHeader message = (IRenderableMessageHeader)messageController.generateDouble(); + + List objectContexts = new List { + new Contact() + }; + + messageController + .when( 'getSeverity' ) + .returns( MessageRendererEngine.Severity.Info ) + .also() + .when( 'getObjectContexts' ) + .returns( objectContexts ); + + MessageRendererEngine.SobjectMessageAdder renderer = new MessageRendererEngine.SobjectMessageAdder(); + + Test.startTest(); + Boolean messageRendered = renderer.render( message ); + Test.stopTest(); + + System.assert( ! messageRendered, 'SobjectMessageAdder, when render is called with an info or warning header message, will return false' ); + + List errors; + errors = objectContexts[0].getErrors(); + System.assertEquals( 0, errors.size(), 'SobjectMessageAdder, when render is called with an info or warning header message, will not add any messages to the sobjects' ); + } + + @isTest + private static void SobjectMessageAdder_whenRenderIsCalledAndThereAreNoObjectContexts_willNotAddErrors() // NOPMD: Test method name format + { + Amoss_Instance messageController = new Amoss_Instance( IRenderableMessageHeader.class ); + IRenderableMessageHeader message = (IRenderableMessageHeader)messageController.generateDouble(); + + Amoss_Instance detailController = new Amoss_Instance( IRenderableMessageDetail.class ); + IRenderableMessageDetail detail = (IRenderableMessageDetail)detailController.generateDouble(); + + messageController + .when( 'getSeverity' ) + .returns( MessageRendererEngine.Severity.Error ) + .also() + .when( 'getObjectContexts' ) + .returns( new List() ); + + MessageRendererEngine.SobjectMessageAdder renderer = new MessageRendererEngine.SobjectMessageAdder(); + + Test.startTest(); + Boolean messageRendered = renderer.render( message ); + Test.stopTest(); + + System.assert( ! messageRendered, 'SobjectMessageAdder, when render is called with an error message that has no object contexts, will return false' ); + } } \ No newline at end of file diff --git a/scripts/helpers/test-and-show-fails.sh b/scripts/helpers/run-tests-and-show-fails.sh similarity index 100% rename from scripts/helpers/test-and-show-fails.sh rename to scripts/helpers/run-tests-and-show-fails.sh