diff --git a/sfdx-source/apex-mocks/main/classes/fflib_ApexMocksUtils.cls b/sfdx-source/apex-mocks/main/classes/fflib_ApexMocksUtils.cls index e9539967..3709b96c 100644 --- a/sfdx-source/apex-mocks/main/classes/fflib_ApexMocksUtils.cls +++ b/sfdx-source/apex-mocks/main/classes/fflib_ApexMocksUtils.cls @@ -189,39 +189,43 @@ public class fflib_ApexMocksUtils private static void streamTokens(JSONParser fromStream, JSONGenerator toStream, JSONParserEvents events) { Integer depth = 0; - while (fromStream.nextToken()!=null) + while (fromStream.nextToken() != null) { // Give event handler chance to inject - if(events!=null) + if (events != null) { events.nextToken(fromStream, depth, toStream); - // Forward to output stream - JSONToken currentToken = fromStream.getCurrentToken(); - if(currentToken == JSONToken.START_ARRAY) { - toStream.writeStartArray(); - depth++; - } - else if(currentToken == JSONToken.START_OBJECT) { - toStream.writeStartObject(); - depth++; } - else if(currentToken == JSONToken.FIELD_NAME) - toStream.writeFieldName(fromStream.getCurrentName()); - else if(currentToken == JSONToken.VALUE_STRING || - currentToken == JSONToken.VALUE_FALSE || - currentToken == JSONToken.VALUE_TRUE || - currentToken == JSONToken.VALUE_NUMBER_FLOAT || - currentToken == JSONToken.VALUE_NUMBER_INT) - toStream.writeString(fromStream.getText()); - else if(currentToken == JSONToken.END_OBJECT) { - toStream.writeEndObject(); - depth--; - } - else if(currentToken == JSONToken.END_ARRAY) { - toStream.writeEndArray(); - depth--; + + // Forward to output stream + switch on fromStream.getCurrentToken() { + when START_ARRAY { + toStream.writeStartArray(); + depth++; + } + when START_OBJECT { + toStream.writeStartObject(); + depth++; + } + when FIELD_NAME { + toStream.writeFieldName(fromStream.getCurrentName()); + } + when VALUE_STRING, VALUE_FALSE, VALUE_TRUE, VALUE_NUMBER_FLOAT, VALUE_NUMBER_INT { + toStream.writeString(fromStream.getText()); + } + when VALUE_NULL { + toStream.writeNull(); + } + when END_OBJECT { + toStream.writeEndObject(); + depth--; + } + when END_ARRAY { + toStream.writeEndArray(); + depth--; + } } // Don't continue to stream beyond the initial starting point - if(depth==0) + if (depth == 0) break; } } diff --git a/sfdx-source/apex-mocks/test/classes/fflib_ApexMocksUtilsTest.cls b/sfdx-source/apex-mocks/test/classes/fflib_ApexMocksUtilsTest.cls index 0d425c12..b02616b8 100644 --- a/sfdx-source/apex-mocks/test/classes/fflib_ApexMocksUtilsTest.cls +++ b/sfdx-source/apex-mocks/test/classes/fflib_ApexMocksUtilsTest.cls @@ -85,7 +85,8 @@ public class fflib_ApexMocksUtilsTest } @isTest - private static void makeRelationship_GenericOverload_ReturnsObjectsWithRelationFieldSet() { + private static void makeRelationship_GenericOverload_ReturnsObjectsWithRelationFieldSet() + { //Given SObject acc = Schema.getGlobalDescribe().get('Account').newSObject(); acc.put('Id', fflib_IDGenerator.generate(acc.getSObjectType())); @@ -128,8 +129,8 @@ public class fflib_ApexMocksUtilsTest } @isTest - private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidParentType() { - + private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidParentType() + { // Setup parent object SObject acc = Schema.getGlobalDescribe().get('Account').newSObject(); acc.put('Id', fflib_IDGenerator.generate(acc.getSObjectType())); @@ -155,8 +156,8 @@ public class fflib_ApexMocksUtilsTest } @isTest - private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidChildType() { - + private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidChildType() + { // Setup parent object SObject acc = Schema.getGlobalDescribe().get('Account').newSObject(); acc.put('Id', fflib_IDGenerator.generate(acc.getSObjectType())); @@ -182,8 +183,8 @@ public class fflib_ApexMocksUtilsTest } @isTest - private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidFieldName() { - + private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidFieldName() + { // Setup parent object SObject acc = Schema.getGlobalDescribe().get('Account').newSObject(); acc.put('Id', fflib_IDGenerator.generate(acc.getSObjectType())); @@ -208,6 +209,67 @@ public class fflib_ApexMocksUtilsTest System.Assert.areEqual('SObject field not found: MyInvalidField', errorMessage); } + @IsTest + private static void makeRelationship_ObjectWithNull_DoesNotThrowErrorOnJSONExceptionCanNotWriteAFieldNameExpectingAValue() + { + // Given + Product2 prod1 = new Product2( + Id = fflib_IDGenerator.generate(Product2.SObjectType), + Name = 'Product1', + ProductCode = 'P1', + Description = null, + StockKeepingUnit = 'P1' + ); + + Product2 prod2 = new Product2( + Id = fflib_IDGenerator.generate(Product2.SObjectType), + Name = 'Product2', + ProductCode = 'P2', + Description = 'this is another product', + StockKeepingUnit = 'P2' + ); + + OrderItem oi1 = new OrderItem( + Id = fflib_IDGenerator.generate(OrderItem.SObjectType), + Product2Id = prod1.Id, + Product2 = prod1, + UnitPrice = 10, + Quantity = 1 + ); + + OrderItem oi2 = new OrderItem( + Id = fflib_IDGenerator.generate(OrderItem.SObjectType), + Product2Id = prod2.Id, + Product2 = prod2, + UnitPrice = 10, + Quantity = 1 + ); + + Order order = new Order(); + + Exception exceptionThatWasCalled = null; + + // When + Test.startTest(); + + try { + fflib_ApexMocksUtils.makeRelationship( + List.class, + new List{ order }, + OrderItem.OrderId, + new List>{ new List{oi1, oi2} } + ); + } catch (JSONException e) { + exceptionThatWasCalled = e; + } + + Test.stopTest(); + + // Then + System.debug(exceptionThatWasCalled); + Assert.isNull(exceptionThatWasCalled, 'Exception should not have been called'); + } + @isTest static void setReadOnlyFields_CreatedByIdSetToCurrentUserId_IdFieldSetSuccessfully() {