10

We need to use database.insertImmediate(). It returns List<Database.SaveResult>.

Now, we want to mock the database.insertImmediate() and not do the dml call and need to be able mock the Database.saveResult as well. Is there any native way to mock it, or should I define an Interface or class that can work with Database.SaveResult?

  • 6
    For those voting to close, kindly take some time to actually read the question instead of just hopping on the close-vote train. This question does fall in the scope of the site (Salesforce + specific question + can be answered specifically). – Derek F Mar 20 '18 at 16:11
11

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.

5

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.

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.