10

I am facing an issue when converting an Opportunity to and then from JSON. If I put that in a test, the assertion fails when comparing both Opportunities.

Here is my code:

Test case:

static testMethod void opportunityCanBeConvertedToJSONFormatAndBack () {

    Opportunity opportunity = Build.anOpportunity().build();
    Opportunity jsonOpportunity = Opportunities.opportunityFromJSON( Opportunities.opportunityToJSON(opportunity) );

    // all this assertions pass
    System.assertEquals(opportunity.Name, jsonOpportunity.Name);
    System.assertEquals(opportunity.StageName, jsonOpportunity.StageName);
    System.assertEquals(opportunity.AccountId, jsonOpportunity.AccountId);
    System.assertEquals(opportunity.Amount, jsonOpportunity.Amount);
    System.assertEquals(opportunity.Sale_Steps__c, jsonOpportunity.Sale_Steps__c);
    System.assertEquals(opportunity.CloseDate, jsonOpportunity.CloseDate);

    // this assertion fails... 
    System.assertEquals(opportunity, jsonOpportunity);
}

The Build class creates the opportunity as follows:

public Opportunity build () {
    if (account == null) {
        account = anAccount().build();
        insert account;
    }
    Opportunity opp = new Opportunity(Name = name,
                                      CloseDate = Date.today(),
                                      StageName = 'Opportunity stage name',
                                      AccountId = account.Id,
                                      Amount = this.anAmount,
                                      Sale_Steps__c = saleStep
    );

    return opp;
}

And finally, this is how the Opportunities class makes the JSON convertion:

public static String opportunityToJSON(Opportunity opp) {
    return System.Json.serialize(opp);
}

public static Opportunity opportunityFromJSON(String json) {
    return (Opportunity) System.Json.deserialize(json, Opportunity.class);
}

Finally, the error message shows the same string conversion for the Opportunities,

Assertion Failed: 
Expected: Opportunity:{Name=An opportunity, StageName=Opportunity stage name, Amount=null, AccountId=001i000000oVNChAAO, Sale_Steps__c=Prospecting, CloseDate=2014-04-22 00:00:00}, 
Actual: Opportunity:{Name=An opportunity, StageName=Opportunity stage name, Amount=null, AccountId=001i000000oVNChAAO, Sale_Steps__c=Prospecting, CloseDate=2014-04-22 00:00:00}

so I am guessing that it should be a deeper comparison that is failing (maybe a TZ, or something inside the Account?), but I can't figure it out, so any help will be really appreciated.

Thanks in advance! Juan M.

Update

I forgot to say that using System.assert and comparing with == also fails.

  • 3
    You may have already seen this thread, but fyi: developer.salesforce.com/forums?id=906F00000008xsmIAA. – Keith C Apr 22 '14 at 14:01
  • Thanks for the suggestion! I have seen that thread and all the proposed solutions involve comparing objects field by field, or using String representations. I am currently using one of this methods, but I see it as a workaround. I am trying to find out why standard comparison does not work, or why it can't be used. – Juan Alvarez Apr 22 '14 at 14:44
  • Yep would be good to understand the root cause. – Keith C Apr 22 '14 at 14:47
  • 1
    I suggest you go through all the fields using describe and assert each one individually. According to documentation, the == is based in comparing each field. This should point to what changes. salesforce.com/us/developer/docs/apexcode/Content/… – Acuariano Apr 22 '14 at 16:12
  • 1
    Certainly seems like a bug, I flagged it with the apex team. – superfell Apr 23 '14 at 21:28
3

I tried comparing each field separately using describe and it works. But the equals for opportunity still fails. I think this is a bug. Here's the code:

@isTest
class OpportunityToJsonBug {
    private static testMethod void testBug() {
        Opportunity opp = new Opportunity(Name = 'Test Opp', StageName = 'Prospecting');
        String json = System.Json.serialize(opp);
        Opportunity jsonOpp = (Opportunity) System.Json.deserialize(json, Opportunity.class);
        Map<String, Schema.SObjectField> M = Schema.SObjectType.Opportunity.fields.getMap();
        for(String fieldName :  M.keySet()) {
             Object oppField  = opp.get(fieldName);
             Object jsonOppField  = jsonOpp.get(fieldName);
             System.assertEquals(oppField, jsonOppField, 'Failed when comparing field ' + fieldName);
        }

        Opportunity controlOpp = new Opportunity(Name = 'Test Opp', StageName = 'Prospecting');
        System.assertEquals(opp, controlOpp);

        // fails here...        
        System.assertEquals(opp, jsonOpp);
    }
}
  • Thanks! Where is one supposed to report this? – Juan Alvarez Apr 22 '14 at 18:40
  • 1
    @JuanAlvarez Open a case with Salesforce Support – Alan Morey Apr 22 '14 at 18:42
  • Reported! I will let you know as soon as I have news. Thanks! – Juan Alvarez Apr 22 '14 at 18:56
  • Not sure if it helps, but I was able to replicated this for all Fields on an Account and got same error. – CoryCowgill Apr 23 '14 at 21:13
  • Opportunity a = new Opportunity(name='test1'); Account a1 = new Account(name = 'woop'); Account a2 = new Account(name = 'woop'); Account a3 = (Account)JSON.deserialize('{"name" : "woop"}', Account.class); Account a4 = (Account)JSON.deserialize(JSON.serialize(a1), Account.class); System.debug( a1 == a2 ); // true System.debug( a1 === a2); // false System.debug( a3 == a1 ); // true System.debug( a4 == a1 ); // false but should be true – CoryCowgill Apr 23 '14 at 21:14
0

Looks like it has been fixed in Winter 16.

http://releasenotes.docs.salesforce.com/en-us/winter16/release-notes/rn_apex_json_ids.htm

Thanks! Juan M.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.