0

I am not able to understand the following behavior:

  1. New list to be inserted in an apex class using fflib/UoW uow.registerNew(myList)

This is the output using System.debug(JSON.serialize(myList));

WorkingHours__c:{End__c=2021-11-22 15:00:00, WorkShift__c=a1R000000000004EAA, Start__c=2021-11-22 09:00:00, WorkPlan__c=a1Q000000000003EAA, User__c=005000000000001AAA}

  1. Mocked list created using sfab_FabricatedSObject to test the registerNew and added to the mocks.verify

((fflib_ISObjectUnitOfWork) mocks.verify(unitOfWorkMock)).registerNew(myMockedList);

This is the output using System.debug(JSON.serialize(myMockedList)):

WorkingHours__c:{Start__c=2021-11-22 09:00:00, End__c=2021-11-22 15:00:00, User__c=005000000000001AAA, WorkShift__c=a1R000000000004EAA, WorkPlan__c=a1Q000000000003EAA}

Finally mocks.verify is throwing an exception because both lists are not equals. As a double check, comparing both lists using List1.equals(List2) again is returning false.

What's the reason?

EDIT:

  1. Trying to debug the issue, I identify that removing Start__c and End__c (both datetime fields) from both lists the problem doesnt exist. mocks.verify and List1.equals(List2) are returning true

  2. As a workaround, instead of comparing directly both lists, I am going to use the fflib_Match.sObjectsWith(toMatch) comparing one by one all the values, in this case again is working perfectly:

        for(WorkingHours__c wh : workingHours){
            toMatch.add(new Map<SObjectField, Object>{
                    WorkingHours__c.WorkShift__c => wh.WorkShift__c,
                    WorkingHours__c.WorkPlan__c =>  wh.WorkPlan__c,
                    WorkingHours__c.User__c => wh.User__c,
                    WorkingHours__c.Start__c => wh.Start__c,
                    WorkingHours__c.End__c => wh.End__c
            });
        }

        ((fflib_ISObjectUnitOfWork) mocks.verify(unitOfWorkMock)).registerNew(fflib_Match.sObjectsWith(toMatch));```
1
  • using fflib_Match.sObjectWith is the preferred solution and to use a UtilDate class / property that you can dependency inject a fixed today/now in testmethods gets around your start and end date issue
    – cropredy
    Nov 16, 2021 at 2:15

1 Answer 1

0

All real SObjects are allocated an Id, CreatedDate, ... when they are inserted into the database. A mocking framework can't duplicate these values (e.g. does not know what the next Id value to allocate is, might get the time wrong by a second).

Comparing SObjects by equality of SObject or lists of SObjects - that automatically checks every populated field - is fragile at the best of times. Hence typically the Id is used for identity and equality is best checked by comparing specific fields. That can be done using e.g.:

    SObjectField[] fields = new SObjectField[] {
        Opportunity.Id,
        Opportunity.AccountId,
        Opportunity.Name,
        Opportunity.CloseDate,
        Opportunity.Amount,
        Opportunity.StageName,
        Opportunity.Description,
        Opportunity.RecordTypeId
    };

    SObject expected = ...;
    SObject actual = ...;

    for (SObjectField f : fields) {
        System.assertEquals(expected.get(f), actual.get(f), 'field=' + f);
    }

with the list case a matter of wrapping in code that iterates over both lists.

2
  • Real list (myList) is not inserted yet, is the one captured in uow.registerNew(myList);, so the Id doesnt exist yet...Let me add more pieces of code to the question to clarify it. Nov 15, 2021 at 23:06
  • @lopez.regalado.fj So compare field by field not including the Id field.
    – Keith C
    Nov 16, 2021 at 7:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .