1

I am writing tests for a flow utility and have been failing tests due to Salesforce by default comparing custom class instances by reference instead of values. I added an equals method to my output class to override this behavior:

public class Result {
    @invocableVariable(label='Processed Multi-Select Picklist' description='The Multi-Select Picklist data with the requested entry removed')
    public String picklist;

    public Boolean equals(Result r) {
        return picklist == r.picklist;
    }
}

This is fine when I'm comparing a single instance of the class -- for example, this test passes fine:

@isTest static void FoundNoDuplicate() {
    List<MultiSelectRemoveAction.Request> requests = new List<MultiSelectRemoveACtion.Request>();
    MultiSelectRemoveAction.Request fndReq = new MultiSelectRemoveAction.Request();
    fndreq.picklist = 'Hello;World;';
    fndreq.entry = 'World';
    requests.add(fndreq);
    List<MultiSelectRemoveAction.Result> res = MultiSelectRemoveAction.removeEntry(requests);
    List<MultiSelectRemoveAction.Result> expectedResultList = new List<MultiSelectRemoveAction.Result>();
    MultiSelectRemoveAction.Result expectedResult = new MultiSelectRemoveAction.Result();
    expectedResult.picklist = 'Hello;';
    expectedResultList.add(expectedResult);
    System.assert(res.get(0).equals(expectedResultList.get(0)));
}

However, a list of instances still compares by reference instead of values. So the same method comparing a full list, such as:

@isTest static void FoundNoDuplicate() {
    List<MultiSelectRemoveAction.Request> requests = new List<MultiSelectRemoveACtion.Request>();
    MultiSelectRemoveAction.Request fndReq = new MultiSelectRemoveAction.Request();
    fndreq.picklist = 'Hello;World;';
    fndreq.entry = 'World';
    requests.add(fndreq);
    List<MultiSelectRemoveAction.Result> res = MultiSelectRemoveAction.removeEntry(requests);
    List<MultiSelectRemoveAction.Result> expectedResultList = new List<MultiSelectRemoveAction.Result>();
    MultiSelectRemoveAction.Result expectedResult = new MultiSelectRemoveAction.Result();
    expectedResult.picklist = 'Hello;';
    expectedResultList.add(expectedResult);
    System.assert(res.equals(expectedResultList));
}

fails with

<TestClass>.FoundNoDuplicate  Fail     System.AssertException: Assertion Failed: Expected: (Result:[picklist=Hello;]), Actual: (Result:[picklist=Hello;])

Obviously for now I'm only comparing single values but it would be great to be able to test full lists of values without having to address each index in turn or do substantial post-processing. Shouldn't a list inherit equality tests from the element class?

4

I recommend you also implement hashCode per the contract in Java Object for hashCode that includes:

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

as otherwise some algorithms will fail. You don't include the implementation code so this is a best guess.

(Apex runs in a JVM and uses many Java conventions.)

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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