1

We're big fans of doing unit tests using as little DML as possible, mocking SObjects using various techniques

Here's a simple example

public class FoosService {
 public void doBar(Set<Id> ids) {
  ... do work ...
  ... oops ... throw BarException
 }
}

public class FoosDomain {

 public void onAfterInsert(SObject[] records) {
    try {
      FooService.doBar(new Map<Id,SObject>(records).keySet();
    }
    catch (FoosService.BarException e) {
      // apply addError(e) to relevant rows in records 
    }
 }
} 

In the unit testmethod:

Foo__c[] mockFoos = new List<Foo__c> {
  new Foo__c(...),
  new Foo__c(...)  // causes exception in FoosService.doBar
};
new FoosDomain.onAfterInsert(mockFoos);

you want to be able to do this:

System.assertEquals(true,mockFoos[1].hasError(),'sb marked as error');

but there is no SObject method to see if a given SObject has had addError(...) applied to it.

Known workarounds:

fflib-apex-common fflib_SObjectDomain class which supports this testable construction:

someSobject.addError(error('message',someSobject));

System.assertEquals('message',
    fflib_SObjectDomain.Errors.getAll()[1].message);

and as we're an fflib shop, I'm happy to use this

Is there some other "trick" I don't know about to discover in an assert that a non-DML'd SObject has had addError applied?

2 Answers 2

2

Yes. Weirdly enough, ApexPages.hasMessages() returns true when any record has had addError called on it.

Account record = new Account();
record.addError('Some message');
system.assert(ApexPages.hasMessages(), 'Informative message');

You won't be able to test which records have hit a validation, but you can tell if any have. Design your tests accordingly.

5
  • Interesting. I tried this in anonymous apex but that fails. Maybe doesn’t matter in test method context.
    – cropredy
    Commented Dec 21, 2018 at 2:40
  • It worked for me in anonymous apex. I didn't post it here before trying it out. Strange.
    – Adrian Larson
    Commented Dec 21, 2018 at 3:29
  • This is probably undocumented behavior because it's not reliable? I've previously been told that in unit tests, they do not initialize the full "visualforce engine", so things that depend on it may not work. I didn't get any specifics, though, but I remember it was because of a bug I had.
    – sfdcfox
    Commented Dec 21, 2018 at 3:43
  • @sfdcfox so - i run Adrian's snippet in DC and it works; I run in Illuminated Cloud IDE or Workbench anonymous Apex and I get Error on line 3, column 1: System.FinalException: ApexPages.hasMessages can only be called from a Visualforce page AnonymousBlock: line 3, column 1
    – cropredy
    Commented Dec 21, 2018 at 17:26
  • 1
    @cropredy That's kind of what I'd expect. DC is actually a VF page under the covers.
    – sfdcfox
    Commented Dec 21, 2018 at 19:21
1

In V50, Apex SObject class now has two new useful methods to solve this issue

  • Boolean hasErrors()
  • Database.Error[] getErrors()

You must log in to answer this question.

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