How to mock a Database.saveresult?

You can create "fake" system objects, but, of course, be wary of doing so in a way that will break their internal implementation.

Here's an example of a successful save:

Database.SaveResult sr = (Database.SaveResult)
    JSON.deserialize('{"success":true,"id":"0013000000abcde"}', Database.SaveResult.class);

And a failed save:

Database.SaveResult sr = (Database.SaveResult)
    JSON.deserialize('{"success":false,"errors":[{"message":"You cannot do this...","statusCode":"FIELD_CUSTOM_VALIDATION_EXCEPTION"}]}', Database.SaveResult.class);

You'll need to figure out a way to inject the values into whatever you're testing, but without seeing your code, it's hard to tell exactly how you might do that in your specific case.


Salesforce has the Stub API to implement mocking:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_stub_api.htm

But, the list of restrictions is pretty eye-watering:

  • The object being mocked must be in the same namespace as the call to the Test.createStub() method. However, the implementation of the StubProvider interface can be in another namespace.
  • You can’t mock the following Apex elements.
    • Static methods (including future methods)
    • Private methods
    • Properties (getters and setters)
    • Triggers
    • Inner classes
    • System types
    • Classes that implement the Batchable interface
    • Classes that have only private constructors
  • Iterators can’t be used as return types or parameter types.

Notably, you can't mock system types.

Also, I think the lack of support for proper reflection in Apex means that using the Stubs API is bound to lead to some horrible code as you figure out which method you are supposed to be mocking.

I recently used the pattern you suggested to mock the Reports system classes and it worked well.

I had an abstract class for the system Reports API. Then I had one implementation that delegates to the system classes, and one which was a mock. I switched in the mock by using @TestVisible and was able to test everything pretty well.